scala types macros scala-2.10 scala-macros

Tipo de retorno estático de las macros de Scala



types scala-2.10 (1)

Así que tengo esta macro:

import language.experimental.macros import scala.reflect.macros.Context class Foo class Bar extends Foo { def launchMissiles = "launching" } object FooExample { def foo: Foo = macro foo_impl def foo_impl(c: Context): c.Expr[Foo] = c.Expr[Foo](c.universe.reify(new Bar).tree) }

He dicho tres veces que quiero que foo devuelva un Foo y, sin embargo, puedo hacer lo siguiente (en 2.10.0-RC3):

scala> FooExample.foo res0: Bar = Bar@4118f8dd scala> res0.launchMissiles res1: String = launching

Lo mismo ocurre si c.Expr parámetros de tipo en c.Expr . Si realmente quiero asegurarme de que quien llama a foo no puede ver que están obteniendo un Bar , tengo que agregar una adscripción de tipo en el árbol mismo.

Esto es realmente genial, significa, por ejemplo, que puedo apuntar una macro a un esquema de algún tipo y crear una subclase anónima de alguna clase de Vocabulary con métodos miembros que representan términos en el vocabulario, y estos estarán disponibles en el objeto devuelto.

Sin embargo, me gustaría entender exactamente lo que estoy haciendo, así que tengo un par de preguntas. Primero, ¿para qué sirve realmente el tipo de devolución en el método foo ? ¿Está solo disponible para la documentación (opcional)? Claramente restringe el tipo de devolución (por ejemplo, no puedo cambiarlo a Int en este caso), y si lo elimino por completo me sale un error como este:

scala> FooExample.foo <console>:8: error: type mismatch; found : Bar required: Nothing FooExample.foo ^

Pero puedo cambiarlo a Any y todavía obtener un Bar estáticamente tipificado cuando llamo a foo .

En segundo lugar, ¿este comportamiento está especificado en alguna parte? Esto parece un conjunto bastante elemental de problemas, pero no he podido buscar una explicación o discusión clara.


Este comportamiento no está especificado pero es intencionado, aunque podría parecer confuso. Planeamos desarrollar el papel del tipo de retorno en macro firmas, pero en este momento siento que la flexibilidad es algo bueno de tener.

También a veces el comportamiento es inconsistente, por ejemplo, cuando la macro se captura en el medio de la inferencia de tipo, se usará su firma estática (es decir, Foo en su ejemplo), no el tipo de la expansión real. Esto se debe a que la expansión de macros se retrasa intencionalmente hasta que se realiza la inferencia de tipos (para que las implementaciones de macros puedan ver tipos inferidos, no tipos de vars). Esta es una solución de compromiso y no necesariamente la mejor, por lo que estamos planeando volver a visitarla pronto: https://issues.scala-lang.org/browse/SI-6755 .

Otro problema en este departamento es con macros implícitas. Cuando el tipo de devolución de una macro implícita es genérico y debe inferirse a partir del tipo solicitado de un valor implícito, suceden cosas malas. Esto hace que actualmente sea imposible usar macros para generar etiquetas de tipo: https://issues.scala-lang.org/browse/SI-5923 .