【问题标题】:Structural types in Dotty/Scala 3 compiled failed?Dotty/Scala 3 中的结构类型编译失败?
【发布时间】:2020-09-21 20:00:23
【问题描述】:

我测试了以下结构类型的代码:

trait Data

object Main
{
  def main(args: Array[String]): Unit =
  {
    val data = new Data {
      val value: Int = 1
    }

    println(data.value)
  }
}

它在 Scala 2.13.2 中编译成功,但在 Dotty/Scala3 中编译失败。如何在 Dotty/Scala3 中使用结构类型?谢谢!

【问题讨论】:

标签: scala structural-typing dotty scala-3


【解决方案1】:

据我所知:

  • 推理发生了变化,因此您必须明确地细化类型:
    val data: Data { val value: Int } = new Data {
      val value: Int = 1
    }
    
    运行dotr可以看得很清楚,查看推断的类型是什么
  • 要使用细化,您必须让编译器知道您不介意反射
    import reflect.Selectable.reflectiveSelectable
    

把它放在一起:

import reflect.Selectable.reflectiveSelectable

trait Data

object Main
{
  def main(args: Array[String]): Unit =
  {
    val data: Data { val value: Int } = new Data {
      val value: Int = 1
    }

    println(data.value)
  }
}

我想你必须这样做的原因是因为很多时候一个人不想进行细化,一个人拥有它(例如测试所有测试夹具new Fixture { ... } 是不必要的细化类型)。另一个是在访问细化时(在 Scala 2 中)细化会使用反射,这会导致性能损失——因此我们应该有意识地而不是意外地这样做。

在 Scala 3 中,结构类型使用 dynamics 实现,这需要混合 Selectable 特征。因此,您必须导入 scala.reflect.Selectable.reflectiveSelectable 隐式转换以使其像在 Scala 2 中一样工作。如果您想让事情像之前一样工作,您可以按照 @Dmytro Mitin 的建议添加 import reflect.Selectable.{ given _ }(并添加反射回来) .

您可以尝试在全局范围内进行,例如exporting 将其放入您的包裹中,但您将自行承担风险。

【讨论】:

  • 导入也可以写成import reflect.Selectable.{ given _ }
  • 实际上,我认为旧式结构类型对于使用 Scala 更像是一种“动态”语言很有用,而无需显式声明类型,同时保持静态类型检查。新式结构类型在书写类型时非常繁琐。我真的希望 Scala 3 保持旧式结构类型可用。有可能吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多