最近在Strange Loop的演讲中,Martin Odersky阐述了他对Scala未来版本Dotty的看法.我知道这是正在进行中的工作,由于许多可能的向后兼容性问题,它甚至可能不会流入Scala(至少不会非常快).但如果它发生了,我们今天如何在Scala中编程以与Dotty向前兼容?我没有从谈话中得到所有想法,所以我希望有更深刻的人总结这些变化,并描述我们如何为他们做好准备.
我正在阅读Scala 3并发现了dotty.我试图了解它是什么.我在某处读到"这是新的编译器",在某处我读到"它是Scala 3的一部分",在某处我读到"Dotty是新的Scala 3".
有人可以向我解释一下究竟是什么?在外行和技术方面?
PS:我已经在StackOverflow上读过了dotty的标签信息但是并没有真正理解它.
可疑这个帖子的至少一部分可能是愚人节的笑话,我开始在我的Linux笔记本电脑上安装Dotty并且很高兴并且惊讶地发现它看起来完全是直的 - 我能够得到Fibonacci函数给定德语在REPL工作正常.
现在我想在IntelliJ IDE中用德语编写Dotty/Scala,但到目前为止还没有设法实现这一点,或者就英语语言'Hello World'而言,Dotty编译失败并出现SBT错误,见下文(对象的IntelliJ代码窗口中没有错误).
通过IntelliJ新项目对话框打开一个新的Dotty项目会在我的.ivy2目录中添加一个新的Dotty实例,这与我在REPL中使用的实例不同.我找到了Felix Mulder的Dotty插件,但我不确定如何使用源代码插件.项目建立后:
Expression Def.Setting[SomeType] must conform to DslEntry in SBT file
我收到此错误日志警告(两次):
Binary version (0.1.1-20170410-0bd7821-NIGHTLY) for dependency
ch.epfl.lamp#scala-library;0.1.1-20170410-0bd7821-NIGHTLY in
default#skala_2.11;0.1-SNAPSHOT differs from Scala binary version in
project (2.11).
我认为这可能是我的环境变量中的路径skala
和dotty
路径的结果PATH
.
在第3点搜索错误消息让我在这里:我可以切换到一个非常容易理解的非捆绑SBT,但是HW仍然无法编译,反而给出了相当长的SBT错误.
不幸的是,我不理解build.sbt中条目的语法,足以根据murmelssonic的建议改变它们.如果我必须学习那么好,我相信我可以.
我相信我已阅读帖子,这些帖子表明build.sbt错误可以忽略,因为它们实际上并没有导致编译错误,但我无法确认这一点,因为我还无法编译任何内容.即使这是真的,我想消除这些,最好不要掩盖合法的警告和错误.
我的问题可能更好地表达为"我如何安装IntelliJ的Dotty插件?",但我不确定这是这一系列症状的完整解决方案.
系统信息:
sbt version
sbt目录中的命令行,通过更改IntelliJ设置使用).我正在尝试执行以下操作
trait Stateful {
type State
}
case class SystemState(system: Stateful, state: system.State) // does not compile
Run Code Online (Sandbox Code Playgroud)
也就是说,类型state
取决于(的值)system
.但是,不支持:
非法依赖方法类型:参数出现在同一节中的另一个参数的类型或更早的参数中
使用函数参数,我可以将参数拆分为两个参数列表,这对于案例类构造函数是不可能的:
def f(system: Stateful)(state: system.State): Unit = {} // compiles
Run Code Online (Sandbox Code Playgroud)
我能做的最好的事情是:
case class SystemState[S](system: Stateful { type State = S }, state: S) // compiles
Run Code Online (Sandbox Code Playgroud)
但我认为没有类型参数应该是可能的,因为在dotty中,我认为类型参数是desugared类型成员.
那么我的问题是,这可以在没有类型参数的情况下表达吗?
在更一般的上下文中,我正在探索类型成员可以用类型成员替换类型参数的程度,何时这样做是个好主意.
在2013 年的这个问题中,奥德斯基先生指出,"现在判断"像Scalaz这样的图书馆是否能够在Dotty下存在(至少在他们当前的状态下),这是由于高级和存在类型的阉割所致.
在过去的时间里,Dotty对Scalaz&Cats的影响已被阐明了吗?内置效果和记录等提议的功能是否会改变这些项目的范围?
我知道Dotty仍然可以替代scalac,但是当我考虑投入时间将纯粹的功能结构和方法应用到我的工作中时,我认为考虑其旗舰库的未来很重要.
既然Dotty显然已经准备好编译更大的项目了,我想知道是否有一种简单的方法可以将它用作sbt项目中Scalac的替代品?就像我有以下内容build.sbt
:
name := "Foo"
scalaVersion := "2.11.7"
Run Code Online (Sandbox Code Playgroud)
我可以采取一些步骤来替换Scalac for Dotc吗?
我正在尝试在 dotty 中学习元编程。具体编译时间代码生成。我认为通过构建一些东西来学习是一种很好的方法。所以我决定制作一个 CSV 解析器,它将行解析为案例类。我想使用dotty宏来生成解码器
trait Decoder[T]{
def decode(str:String):Either[ParseError, T]
}
object Decoder {
inline given stringDec as Decoder[String] = new Decoder[String] {
override def decode(str: String): Either[ParseError, String] = Right(str)
}
inline given intDec as Decoder[Int] = new Decoder[Int] {
override def decode(str: String): Either[ParseError, Int] =
str.toIntOption.toRight(ParseError(str, "value is not valid Int"))
}
inline def forType[T]:Decoder[T] = ${make[T]}
def make[T:Type](using qctx: QuoteContext):Expr[Decoder[T]] = ???
}
Run Code Online (Sandbox Code Playgroud)
我已经为Int
&提供了基本的解码器String
,现在我正在寻找def make[T:Type]
方法的指导。如何T
在此方法中迭代案例类的参数列表?有没有推荐的方法或模式来做到这一点?
我正在尝试通过 Scala 3.0.0-M2 中的宏获取函数名称我提出的解决方案使用 TreeAccumulator
import scala.quoted._
inline def getName[T](inline f: T => Any): String = ${getNameImpl('f)}
def getNameImpl[T](f: Expr[T => Any])(using Quotes): Expr[String] = {
import quotes.reflect._
val acc = new TreeAccumulator[String] {
def foldTree(names: String, tree: Tree)(owner: Symbol): String = tree match {
case Select(_, name) => name
case _ => foldOverTree(names, tree)(owner)
}
}
val fieldName = acc.foldTree(null, Term.of(f))(Symbol.spliceOwner)
Expr(fieldName)
}
Run Code Online (Sandbox Code Playgroud)
调用此代码时会生成函数的名称:
case class B(field1: String)
println(getName[B](_.field1)) // "field1"
Run Code Online (Sandbox Code Playgroud)
我想知道这是否可以使用引号以更简单的方式完成。
我想实现proxy
一些特征A
(例如委托方法调用到一些 rpc 调用),像这样
def clientProxy[A](using Type[A], Quotes): Expr[A] = {
import quotes.reflect._
val defTrees: List[Tree] = TypeRepr.of[A].typeSymbol.memberFields.collect {
case mf if mf.isDefDef =>
???
}
val exprs = Expr.ofList(defTrees.map(_.asExpr))
'{
new A {
$exprs
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是编译器抱怨
A is not a class type
Run Code Online (Sandbox Code Playgroud) 形状列表推断,List[Shape]
但盒装形状列表推断List[Box[Square | Circle]]
scala> sealed trait Shape
| case class Square() extends Shape
| case class Circle() extends Shape
| case class Box[+T <: Shape](t: T)
| List(Square(), Circle())
| List(Box(Square()), Box(Circle()))
val res0: List[Shape & Product & Serializable] = List(Square(), Circle())
val res1: List[Box[Square | Circle]] = List(Box(Square()), Box(Circle()))
Run Code Online (Sandbox Code Playgroud)
为什么res0
不与List[Square | Circle]
对称输入List[Box[Square | Circle]]
,反之亦然?
Dotty根据联合类型定义最小上限
一组类型的最小上限 (lub) 是这些类型的并集。这取代了Scala 2 规范中最小上限的定义。
与此更改相关的统一规则是什么?
dotty ×10
scala ×10
sbt ×2
scala-3 ×2
scala-macros ×2
case-class ×1
macros ×1
reflection ×1
scala-cats ×1
scalaz ×1
subtyping ×1