答案 0 :(得分:32)
“虚拟化”模式匹配器是对现有匹配器的重写。这样做的动机是支持多态嵌入式DSL 的模式匹配虚拟化,与2.10无关。
正如Iulian在下面的评论中所说:这与编译for comprehension的方式非常相似:它们不是直接生成代码,而是转换为foreach
,map
,{{1然后可以将模式匹配转换为一系列方法调用,DSL可以覆盖。默认实现将遵循当前语义,并且挑战在于使其与当前语义一样高效。看来Adriaan非常接近这个目标。 “虚拟化”实现更简单,并修复了当前实现中的几个错误。
“多态嵌入式DSL”是指人们可能在scala中编写不应该在JVM上运行的程序。也就是说,filter
将产生一个描述程序正在做什么的输出。然后可以针对特定架构重新编译。这样的事情have been talked about at ScalaDays 2011。
这次重写最终将成为标准的scala模式匹配器。旧模式匹配器(据我所知)是不可维护的。
答案 1 :(得分:8)
可悲的是,(唯一的)现有答案在多汁位上很低,评论上的链接被打破了。所以,让我尝试在这里添加一些果汁,因为,如果没有其他原因,我自己的参考,当我实际决定在未来做一些事情,看到这个答案是在我做的每一个谷歌搜索之上。
如上所述,虚拟化模式匹配器是对Scala编译器如何处理模式匹配的重写。它有很多用途,其中“虚拟化”部分意味着它是虚拟化scala工作的一部分。这种努力与宏相反:它需要在编译时“运行”的东西,然后移动到运行时。
例如,如果范围内存在正确的定义,则会出现如下语句:
if (false) 1 else 2
而不是编译为字节码分支和文字,甚至优化为文字“2”,实际上编译为以下语句:
__ifThenElse(false, 1, 2)
请参阅scala virtualized wiki以获取更多信息以及一些有用的示例。
然而,我说,模式匹配器重写有很多用途。另一个非常重要的目标是将旧模式匹配器的意大利面条代码,完整或特殊以及角落案例和错误转换为可以更容易推理,扩展和改进的东西。这个重写修复了很多问题,人们刚刚通过问题列表运行示例代码,查找与模式匹配器相关的问题,并将问题标记为“固定”,因为它们有效。它确实有自己的新bug,但规模要小得多。现在,关于新模式匹配器如何工作的信息非常少,但基本上,它转换为一些方法调用,这些调用在编译器中使用Option
monad“实现”。然后进入一个产生最佳字节码的优化阶段。
虽然它被锁定在-Xexperimental
标志后面,但可以引入自己的匹配器。尝试从Scala的测试套件复制的以下代码,带有和不带有该标志:
trait Intf {
type Rep[+T]
type M[+T] = Rep[Maybe[T]]
val __match: Matcher
abstract class Matcher {
// runs the matcher on the given input
def runOrElse[T, U](in: Rep[T])(matcher: Rep[T] => M[U]): Rep[U]
def zero: M[Nothing]
def one[T](x: Rep[T]): M[T]
def guard[T](cond: Rep[Boolean], then: => Rep[T]): M[T]
def isSuccess[T, U](x: Rep[T])(f: Rep[T] => M[U]): Rep[Boolean] // used for isDefinedAt
}
abstract class Maybe[+A] {
def flatMap[B](f: Rep[A] => M[B]): M[B]
def orElse[B >: A](alternative: => M[B]): M[B]
}
implicit def proxyMaybe[A](m: M[A]): Maybe[A]
implicit def repInt(x: Int): Rep[Int]
implicit def repBoolean(x: Boolean): Rep[Boolean]
implicit def repString(x: String): Rep[String]
def test = 7 match { case 5 => "foo" case _ => "bar" }
}
trait Impl extends Intf {
type Rep[+T] = String
object __match extends Matcher {
def runOrElse[T, U](in: Rep[T])(matcher: Rep[T] => M[U]): Rep[U] = ("runOrElse("+ in +", ?" + matcher("?") + ")")
def zero: M[Nothing] = "zero"
def one[T](x: Rep[T]): M[T] = "one("+x.toString+")"
def guard[T](cond: Rep[Boolean], then: => Rep[T]): M[T] = "guard("+cond+","+then+")"
def isSuccess[T, U](x: Rep[T])(f: Rep[T] => M[U]): Rep[Boolean] = ("isSuccess("+x+", ?" + f("?") + ")")
}
implicit def proxyMaybe[A](m: M[A]): Maybe[A] = new Maybe[A] {
def flatMap[B](f: Rep[A] => M[B]): M[B] = m + ".flatMap(? =>"+ f("?") +")"
def orElse[B >: A](alternative: => M[B]): M[B] = m + ".orElse("+ alternative +")"
}
def repInt(x: Int): Rep[Int] = x.toString
def repBoolean(x: Boolean): Rep[Boolean] = x.toString
def repString(x: String): Rep[String] = x
}
object Test extends Impl with Intf with App {
println(test)
}
没有旗帜的结果正是您所期望的:
scala> Test.main(null)
bar
然而,使用-Xexperimental
,可以编译替代匹配“引擎”:
scala> Test.main(null)
runOrElse(7, ?guard(false,?).flatMap(? =>one(foo)).orElse(one(bar)))
有关详情,请参阅PatternMatching和MatchMonadInterface的scaladoc。
免责声明:以上是2.10.0之后的主分支上的Scala版本的提取和运行,因此可能存在差异。我发现自己遗憾地缺乏纯粹的2.10.0或2.10.1环境来测试它。