【发布时间】:2012-01-21 23:02:00
【问题描述】:
【问题讨论】:
-
我从来没有听说过有这样的事情
标签: scala pattern-matching scala-2.10
【问题讨论】:
标签: scala pattern-matching scala-2.10
“虚拟化” 模式匹配器是对现有匹配器的重写。这样做的动机是支持 多态嵌入式 DSL 的模式匹配虚拟化,与 2.10 无关。
正如 Iulian 在下面的 cmets 中所说:这与编译 for-comprehensions 的方式非常相似:不是直接生成代码,而是将它们转换为 foreach、map、filter 等。模式匹配然后可以转换为一系列方法调用,DSL 可以覆盖这些方法调用。默认实现将尊重当前语义,挑战在于使其与当前语义一样高效。看来阿德里安非常接近这个目标。 “虚拟化”实现更简单,并修复了当前实现中的几个错误。
“多态嵌入式 DSL”是指人们可能会在 scala 中编写不应该在 JVM 上运行的程序。也就是说,scalac 将产生一个描述程序正在做什么的输出。然后可以针对特定架构重新编译。这样的事情have been talked about at ScalaDays 2011。
这种重写最终将成为标准的 scala 模式匹配器。旧的模式匹配器(据我了解)无法维护。
【讨论】:
foreach、map、filter 等。然后可以将模式匹配转换为一系列方法调用,DSL 可以覆盖。默认实现将尊重当前语义,挑战在于使其与当前语义一样高效。看来阿德里安非常接近这个目标。 “虚拟化”实现更简单,并修复了当前实现中的几个错误。
可悲的是,(唯一的)现有答案很少有内容,并且评论上的链接已损坏。所以让我在这里尝试添加一些果汁,如果没有其他原因,我自己的参考,当我真正决定将来用它做某事时,因为这个答案是我所做的每个谷歌搜索的顶部。
如前所述,虚拟化模式匹配器是对 Scala 编译器处理模式匹配方式的重写。它有很多用途,其中的“虚拟化”部分意味着它是虚拟化 scala 工作的一部分。这种努力与宏有点相反:它需要在编译时“运行”的东西,然后转移到运行时。
例如,给定范围内的正确定义,这样的语句:
if (false) 1 else 2
实际上并没有被编译为字节码分支和文字,甚至优化为文字“2”,而是编译为以下语句:
__ifThenElse(false, 1, 2)
请参阅scala virtualized wiki 了解更多信息和一些有用的示例。
然而,我说过,模式匹配器重写有很多用途。另一个非常重要的目标是将作为旧模式匹配器、完整或特殊、极端情况和错误的意大利面条代码变成可以更容易推理、扩展和改进的东西。这种重写解决了很多问题,以至于人们只是通过问题列表运行与模式匹配器相关的问题的示例代码,并在工作时将问题标记为“已修复”。它确实有自己的新错误,但规模要小得多。
现在,关于新模式匹配器如何工作的信息很少,但基本上,它转化为一些方法调用,这些方法调用在编译器中使用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 的 scaladocs。
免责声明:以上内容是从 2.10.0 之后的 master 分支上的 Scala 版本中提取和运行的,因此可能存在差异。不过,我发现自己很遗憾缺乏纯 2.10.0 或 2.10.1 环境来测试它。
【讨论】: