什么是scala的实验虚拟模式匹配器?

oxb*_*kes 43 scala pattern-matching scala-2.10

我见过不少几个 提到最近新的"虚拟化"模式斯卡拉匹配.我错过了备忘录,解释它究竟是什么......

小智 32

"虚拟化"模式匹配是现有的匹配器的重写.这样做的动机是支持多态嵌入式DSL的模式匹配虚拟化,与2.10无关.

随着尤利安在下面的评论说:这是非常相似,如何换内涵被编译:不是直接生成代码,它们被翻译为foreach,map,filter等模式匹配可随后被翻译成一系列方法调用,即DSL的可能会覆盖.默认实现将遵循当前语义,并且挑战在于使其与当前语义一样高效.看来Adriaan非常接近这个目标."虚拟化"实现更简单,并修复了当前实现中的几个错误.

"多态嵌入式DSL"是指人们可能在scala中编写不应该在JVM上运行的程序.也就是说,scalac将产生一个描述程序正在做什么的输出.然后可以针对特定架构重新编译.这些事情已在ScalaDays 2011上讨论过.

这种重写最终将成为标准的scala模式匹配器.旧模式匹配器(据我所知)是不可维护的.

  • 它与编译理解的方式非常相似:它们不是直接生成代码,而是转换为`foreach`,`map`,`filter`等.然后,模式匹配可以转换为一系列方法调用,即DSL可以覆盖.默认实现将遵循当前语义,并且挑战在于使其与当前语义一样高效.看来Adriaan非常接近这个目标."虚拟化"实现更简单,并修复了当前实现中的几个错误. (24认同)
  • 我刚刚意识到"Virtpatmat"的意思是"虚拟模式匹配器"而不是以俄罗斯一个不起眼的城市命名 (10认同)
  • 是的,你可以对这里的实现有所了解:https://github.com/adriaanm/scala/blob/topic/virtpatmat/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala作为数据点,scalac由scalac -Yvirtpatmat -optimize编译产生的编译器当前比仅使用-optimize编译的编译器运行速度慢约2%(因此使用旧的模式匹配器) (6认同)

Dan*_*ral 8

可悲的是,(唯一的)现有答案在多汁的位上很少,并且评论上的链接被打破了.所以,让我尝试在这里添加一些果汁,因为,如果没有其他原因,我自己的参考,当我实际决定在未来做一些事情,看到这个答案是在我做的每一个谷歌搜索之上.

如上所述,虚拟化模式匹配器是对Scala编译器如何处理模式匹配的重写.它有很多用途,其中"虚拟化"部分意味着它是虚拟化scala工作的一部分.这种努力与宏相反:它需要在编译时"运行"的东西,然后移动到运行时.

例如,如果范围中存在正确的定义,则会出现如下语句:

if (false) 1 else 2
Run Code Online (Sandbox Code Playgroud)

而不是被编译为字节码分支和文字,甚至优化到文字"2",实际上编译为以下语句:

__ifThenElse(false, 1, 2)
Run Code Online (Sandbox Code Playgroud)

请参阅scala虚拟化wiki以获取更多信息以及一些有用的示例.

然而,我说,模式匹配器重写有很多用途.另一个非常重要的目标是将旧模式匹配器的意大利面条代码,完整或特殊以及角落案例和错误转换为可以更容易推理,扩展和改进的东西.这个重写修复了很多问题,人们刚刚通过问题列表运行示例代码,查找与模式匹配器相关的问题,并将问题标记为"固定",因为它们有效.它确实有自己的新bug,但规模要小得多.

现在,关于新模式匹配器如何工作的信息非常少,但基本上,它转换为一些方法调用,这些调用在编译器中使用Optionmonad "实现" .然后进入产生最佳字节码的优化阶段.

可以引入自己的匹配器,虽然它被锁定在-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)
}
Run Code Online (Sandbox Code Playgroud)

没有旗帜的结果正是您所期望的:

scala> Test.main(null)
bar
Run Code Online (Sandbox Code Playgroud)

-Xexperimental但是,有了替代匹配"引擎"的编译:

scala> Test.main(null)
runOrElse(7, ?guard(false,?).flatMap(? =>one(foo)).orElse(one(bar)))
Run Code Online (Sandbox Code Playgroud)

有关PatternMatching和MatchMonadInterface的scaladoc,请参阅参考资料.

免责声明:以上是2.10.0之后的主分支上的Scala版本提取和运行,因此可能存在差异.不过,我发现自己遗憾地缺乏一个纯粹的2.10.0或2.10.1环境来测试它.