2011-12-16 9 views

Respuesta

32

"virtualizado" patrón de coincidencia es una reescritura del emparejador existente. La motivación para hacer esto fue apoyar la virtualización de la coincidencia de patrones para las DSL polimórficas integradas , no relevante para 2.10.

Como dice Iulian en los comentarios a continuación: es muy similar a la forma de-comprensiones son compilados: en lugar de generar directamente el código, que se traducen a foreach, map, filter etc. Coincidencia de patrones podrían entonces ser traducido a una serie de llamadas a métodos, que las DSL podrían sobrescribir. La implementación predeterminada respetará la semántica actual, y el desafío es hacerlo tan eficiente como el actual. Parece que Adriaan está muy cerca de este objetivo. La implementación 'virtualizada' es más simple y soluciona varios errores en la implementación actual.

Las "DSL incorporadas polimórficas" son la idea de que uno podría escribir programas en scala que no se supone que deben ejecutarse en la JVM. Es decir, scalac producirá una salida que describe lo que está haciendo el programa. Esto puede volverse a compilar contra una arquitectura específica. Tales cosas have been talked about at ScalaDays 2011.

Esta reescritura se convertirá con el tiempo en el modelo estándar de scala. El viejo patrón de coincidencia era (como yo lo entiendo) inmanejable.

+0

No estoy seguro de que "el patrón virtual de compatibilidad sea compatible con la virtualización de coincidencia de patrones" no era algo que no hubiera podido adivinar. ¿Quizás podría explicar qué es la coincidencia de patrones virtualizados en realidad? –

+24

Es muy similar a cómo se compilan las comprensiones: en lugar de generar código directamente, se traducen a 'foreach',' map', 'filter', etc. La coincidencia de patrones se podría traducir a una serie de llamadas a métodos, que las DSL podría sobrescribir La implementación predeterminada respetará la semántica actual, y el desafío es hacerlo tan eficiente como el actual. Parece que Adriaan está muy cerca de este objetivo. La implementación 'virtualizada' es más simple y soluciona varios errores en la implementación actual. –

+0

Hola, Iulian: ¡si tan solo pudiera otorgar "respuesta aceptada" a tu comentario! –

8

Lamentablemente, la (única) respuesta existente es baja en bits jugosos, y los enlaces en los comentarios están rotos. Así que déjame intentar agregar algo de jugo aquí, por lo que, por alguna otra razón, mi propia referencia cuando realmente decida hacer algo con ella en el futuro, ya que esta es la respuesta a cada búsqueda en Google que hago.

El matcher de patrones virtualizados, como se mencionó, es una reescritura de cómo el compilador de Scala maneja la coincidencia de patrones. Sirvió para muchos propósitos, con la parte de "virtualización" de lo que significa que es parte del esfuerzo de scala virtualizado. Ese esfuerzo es un poco lo contrario de las macros: toma las cosas que se "ejecutan" en tiempo de compilación, y luego las mueve al tiempo de ejecución.

Por ejemplo, dada la presencia de la definición apropiada en su alcance, una declaración como esta:

if (false) 1 else 2 

en lugar de ser compilados para ramas de código de bytes y literales, o incluso optimizado para el literal "2", en realidad como se compila la siguiente declaración:

__ifThenElse(false, 1, 2) 

por favor ver la scala virtualized wiki para obtener más información y algunos ejemplos de lo que esto puede ser útil para.

Dije, sin embargo, que la reescritura del patrón de coincidencia sirvió para muchos propósitos. Otro objetivo muy importante fue convertir el código de espagueti que era el viejo patrón de emparejamiento, completo o especial y en casos de esquina e insectos, en algo con lo que se puede razonar, extender y mejorar más fácilmente. Esta reescritura solucionó tantos problemas que las personas simplemente revisaban la lista de problemas ejecutando el código de ejemplo para problemas relacionados con el patrón de coincidencia y marcando los problemas como "corregidos" a medida que trabajaban. Tiene nuevos errores propios, pero a una escala mucho, mucho más pequeña.

Ahora, hay muy poca información sobre cómo funciona el nuevo patrón de emparejamiento, pero, básicamente, se traduce en unas pocas llamadas a métodos que están "implementadas" en el compilador con la mónada Option. Luego entra en una fase de optimización que produce bytecode óptimo.

Es posible presentar su propio comparador, aunque esté bloqueado detrás de una bandera -Xexperimental. Pruebe el siguiente código, copiado del conjunto de pruebas de Scala, con y sin esa bandera:

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) 
} 

El resultado sin la bandera es justo lo que se espera:

scala> Test.main(null) 
bar 

Con -Xexperimental, sin embargo, el alternativa coincidente "motor" se compila:

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

Véase también, para más información, los scaladocs para PatternMatching y la MatchMonadInterface.

Descargo de responsabilidad: lo anterior se extrajo y se ejecutó desde una versión de Scala en la rama principal, después de la 2.10.0, por lo que puede haber diferencias. Sin embargo, lamentablemente me falta un entorno 2.10.0 o 2.10.1 puro para probarlo.

Cuestiones relacionadas