tutorial programacion lenguaje ejemplos scala pattern-matching scala-2.10

tutorial - scala lenguaje de programacion ejemplos



¿Cuál es el equilibrador de patrones virtuales experimentales de Scala? (2)

El marcador de patrón "virtualizado" 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 incorporadas , no relevante para 2.10.

Como dice Iulian en los comentarios a continuación: 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 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.

Las "DSL polimórficas incorporadas" son la idea de que se podrían escribir programas en scala que no deberían ejecutarse en la JVM. Es decir, scalac producirá un resultado que describe lo que está haciendo el programa. Esto puede volverse a compilar contra una arquitectura específica. Tales cosas se han hablado en ScalaDays 2011 .

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

Recientemente, he visto bastantes mentions del nuevo matcher de patrones "virtualizados" para Scala. Me perdí el memo explicando qué era en realidad ...


Tristemente, 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.

La combinación 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 adecuada en el alcance, una declaración como esta:

if (false) 1 else 2

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

__ifThenElse(false, 1, 2)

Consulte la wiki virtualizada de scala para obtener más información y algunos ejemplos de lo que puede ser útil.

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 matcher de patrones, pero, básicamente, se traduce en unas pocas llamadas a métodos que se "implementan" en el compilador con la mónada Option . Luego entra en una fase de optimización que produce bytecode óptimo.

Es posible introducir su propio comparador, aunque esté bloqueado detrás de una bandera -Xexperimental . Pruebe el siguiente código, copiado del banco 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 esperarías:

scala> Test.main(null) bar

Con -Xexperimental , sin embargo, se compila el "motor" de coincidencia alternativo:

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

Consulte también, para obtener más información, los scaladocs para PatternMatching y MatchMonadInterface .

Descargo de responsabilidad: lo anterior fue extraído y ejecutado desde una versión de Scala en la rama principal, después de 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.