2011-12-16 38 views

回答

32

「虛擬化」模式匹配器是對現有匹配器的重寫。這樣做的動機是支持多態嵌入式DSL的模式匹配虛擬化,與2.10無關。

隨着尤利安在下面的評論說:它非常類似於如何換內涵被編譯:不是直接生成代碼,它們被翻譯成foreachmapfilter等模式匹配然後可以轉換爲一系列的方法調用,DSL可以覆蓋。默認實現將尊重當前的語義,挑戰在於使其與當前的效率一樣高效。看來Adriaan非常接近這個目標。 「虛擬化」的實現更簡單,並修復了當前實現中的一些錯誤。

「多態嵌入式DSL」是一種想法,可以用scala編寫不應該在JVM上運行的程序。也就是說,scalac將產生一個描述程序正在做什麼的輸出。然後這可以針對特定的體系結構重新編譯。這樣的東西have been talked about at ScalaDays 2011

這個重寫最終會成爲標準的scala模式匹配器。舊的模式匹配器(據我所知)不可維護。

+0

我不確定「虛擬模式匹配器是否支持模式匹配虛擬化」不是我無法想象的。也許你可以解釋一下虛擬化模式匹配究竟是什麼? – 2011-12-16 14:11:31

8

不幸的是,(唯一的)現有的答案是多汁的低,並且評論的鏈接被打破。因此,讓我試着在這裏添加一些果汁,因爲如果沒有其他原因,我自己的參考,當我實際上決定在將來做什麼,看到這個答案在我做的每一個谷歌搜索的頂部。

虛擬化模式匹配器,如前所述,是重寫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))) 

還可參見更多信息,PatternMatchingMatchMonadInterface的scaladocs。

聲明:上述內容是從主分支上的Scala版本提取並在2.10.0之後運行的,因此可能存在差異。不過,我發現自己很遺憾缺乏純粹的2.10.0或2.10.1環境來測試它。