¿Cómo se implementa la coincidencia de patrones en Scala a nivel de bytecode?
¿Es como una serie de if (x instanceof Foo)
construcciones, o algo más? ¿Cuáles son sus implicaciones de rendimiento?
Por ejemplo, dado el siguiente código (de Scala By Example, páginas 46-48), ¿cómo se vería el código Java equivalente para el eval
método?
abstract class Expr
case class Number(n: Int) extends Expr
case class Sum(e1: Expr, e2: Expr) extends Expr
def eval(e: Expr): Int = e match {
case Number(x) => x
case Sum(l, r) => eval(l) + eval(r)
}
PD: Puedo leer el código de bytes de Java, por lo que una representación de código de bytes sería lo suficientemente buena para mí, pero probablemente sería mejor para los otros lectores saber cómo se vería como código de Java.
PPS ¿El libro Programación en Scala da una respuesta a esta y otras preguntas similares sobre cómo se implementa Scala? He ordenado el libro, pero aún no ha llegado.
performance
scala
pattern-matching
bytecode
Esko Luontola
fuente
fuente
Respuestas:
El nivel bajo se puede explorar con un desensamblador, pero la respuesta corta es que es un montón de if / elses donde el predicado depende del patrón
Hay mucho más que puedes hacer con patrones como o patrones y combinaciones como "case Foo (45, x)", pero en general esas son solo extensiones lógicas de lo que acabo de describir. Los patrones también pueden tener guardias, que son restricciones adicionales en los predicados. También hay casos en los que el compilador puede optimizar la coincidencia de patrones, por ejemplo, cuando hay cierta superposición entre los casos, puede unir un poco las cosas. Los patrones avanzados y la optimización son un área activa de trabajo en el compilador, así que no se sorprenda si el código de bytes mejora sustancialmente sobre estas reglas básicas en las versiones actuales y futuras de Scala.
Además de todo eso, puede escribir sus propios extractores personalizados además de o en lugar de los predeterminados que Scala usa para las clases de casos. Si lo hace, el costo de la coincidencia de patrones es el costo de lo que haga el extractor. Una buena descripción general se encuentra en http://lamp.epfl.ch/~emir/written/MatchingObjectsWithPatterns-TR.pdf
fuente
James (arriba) lo dijo mejor. Sin embargo, si tiene curiosidad, siempre es un buen ejercicio observar el bytecode desmontado. También puede invocar
scalac
con la-print
opción, que imprimirá su programa con todas las funciones específicas de Scala eliminadas. Básicamente es Java en la ropa de Scala. Aquí está lascalac -print
salida relevante para el fragmento de código que proporcionó:fuente
Desde la versión 2.8, Scala ha tenido la anotación @switch . El objetivo es garantizar que la coincidencia de patrones se compilará en un interruptor de tabla o de búsqueda en lugar de una serie de
if
instrucciones condicionales .fuente
@switch
es más eficiente que la coincidencia de patrones regular. así que si todos los casos contienen valores constantes, siempre debe usar@switch
(porque la implementación del código de bytes será la misma que la de Java enswitch
lugar de muchos if-else)