Scala的实验性虚拟模式匹配器是什么?
最近我见到了很多关于scala的新“虚拟化”模式匹配器。 我错过了解释它实际上是什么的备忘录…
“虚拟化”模式匹配器是对现有匹配器的重写。 这样做的动机是支持多态embedded式DSL的模式匹配虚拟化,与2.10无关。
正如Iulian在下面的评论中所说的那样: 它与编译的理解非常相似:不是直接生成代码,而是将其转换为foreach
, map
, filter
等。然后可以将模式匹配转换为一系列的方法调用, DSL可能会覆盖。 默认实现将尊重当前的语义,挑战在于使其与当前的效率一样高效。 看来Adriaan非常接近这个目标。 “虚拟化”的实现更简单,并修复了当前实现中的一些错误。
“多态embedded式DSL”就是人们可以用scala编写程序的思想,而不应该在JVM上运行。 也就是说, scalac
会产生一个描述程序正在做什么的输出。 然后这可以针对特定的体系结构重新编译。 2011年ScalaDays已经讨论过这样的事情。
这个重写将最终成为标准的scala模式匹配器。 旧的模式匹配器(据我所知)是不可维护的。
不幸的是,(唯一的)现有的答案是多汁的低,并在评论链接被打破。 所以,让我试着在这里添加一些果汁,因为如果没有其他理由,我自己的参考,当我实际上决定在未来做什么,看到这个答案是我做的每一个谷歌search的顶部。
如上所述,虚拟化模式匹配器是对Scala编译器如何处理模式匹配的重写。 它有很多用途,其中“虚拟化”部分意味着它是虚拟化scala努力的一部分。 这个努力与macros有点相反:它在编译时需要“运行”,然后移动到运行时。
例如,鉴于范围内存在适当的定义,这样的陈述:
if (false) 1 else 2
而不是被编译成字节码分支和文字,甚至优化到文字“2”,实际上被编译为以下语句:
__ifThenElse(false, 1, 2)
请参阅scala虚拟化维基以获取更多信息和一些可用的示例。
然而,我说,重写模式匹配器有很多目的。 另外一个非常重要的目标是把旧的模式匹配器,全部或特殊的angular落案例和错误的意大利面代码变成可以推理,扩展和改进的东西。 这次重写解决了很多问题,人们只是通过运行示例代码的问题列表来查看与模式匹配器相关的问题,并将问题标记为“固定”。 它确实有自己的新错误,但规模要小得多。
现在,关于新的模式匹配器是如何工作的信息非常less,但基本上,它转化为一些在编译器中用Option
monad“实现”的方法调用。 然后进入产生最佳字节码的优化阶段。
可以引入你自己的匹配器,尽pipe它被locking在一个-Xexperimental
标志之后。 尝试下面的代码,从Scala的testing套件中复制,带有和不带该标志:
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 。
免责声明:以上是从主分支上的Scala版本提取并运行,2.10.0之后,所以可能会有差异。 不过,我发现自己很遗憾缺乏纯粹的2.10.0或者2.10.1环境来testing它。