1/10:Scala 3 迁移技巧和窍门。🧵。重要提示:仔细阅读迁移指南,并利用 scalafix 进行语法更新。这将节省您数小时的手动工作!
2/10:不要急着用新语法替换所有内容!首先,使用 Scala 3 编译器,用旧语法编译你的代码库。新语法有其自身的规则,如果你不熟悉,可能会引发令人困惑的错误,尤其是与旧语法混合使用时。
3/10 当用 `using` 替换隐式参数时,请记住,调用站点上传递的所有显式参数也需要 `using` 关键字!getUserInfo(userId)(using Tracing.noop) // 正确
4/10:忘记使用 `using` 关键字会导致一些难以理解的错误。编译器可能会高亮显示代码中完全不同的部分,这会让调试变得非常困难。我浪费了很多时间才弄清楚到底发生了什么。
5/10:关于 circe 的警告:从半自动派生(例如 `deriveConfiguredCodec`)迁移到 `Codec.derived` 时,请务必小心!`Decoder.derived` 不接受 `Configuration` 作为隐式参数 - 请改用 `Decoder.derivedConfigured`。
6/10:使用新的 derives 语法,你可以完全避免 circe 问题:case class MyClass(...) derives ConfiguredCodec 我差点就把一个 bug 推送到 prod 了,因为我相信 Decoder.derived 的行为也一样。幸亏另一个 bug,我才得以及早发现。
7/10:Doobie 用户:小心那些关于缺少 Get/Put 实例的巨型错误信息。在我的例子中,AnyVal 类是罪魁祸首——编译器无法像以前那样派生实例。
8/10:doobie 问题的解决方案:将 AnyVal 类转换为不透明类型并在伴随对象中提供给定的实例。
9/10:在使用无形元组语法(Scala 3 中已移除)的遗留代码中遇到了挑战。需要一种方法来附加元组元素并转换为 Case 类。最初尝试了 Scala 3 的原生元组语法,但它与 CaseClass.tupled 不兼容。
10/10:在尝试了自定义元组扩展(存在运行时失败风险)之后,我发现 Chimney 库是拼接元组并添加附加值的最佳解决方案。额外福利:我甚至在 Chimney 的最新版本中发现了一个 bug!
你发现了哪些迁移技巧?在下面分享!#Scala #Scala3
奖励#1:您可以将 someContextualResource.flatMap { implicit tracing => ... } 替换为 someContextualResource.flatMap { case given TracingCtx => ... },虽然不完美但可以工作,比在同一个文件和代码库中混合给定和隐式要好。