Статический тип возврата макросов Scala
Итак, у меня есть этот макрос:
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)
}
Я трижды сказал, что хочуfoo
вернутьFoo
и все же я могу сделать следующее (в 2.10.0-RC3):
scala> FooExample.foo
res0: Bar = Bar@4118f8dd
scala> res0.launchMissiles
res1: String = launching
То же самое происходит, если я удаляю параметры типа на любомc.Expr
, Если я действительно хочу убедиться, что тот, кто звонитfoo
не вижу, что они получаютBar
Я должен добавить тип надписи в самом дереве.
Это на самом деле довольно здорово - это означает, например, что я могу указать макрос на какую-то схему и создать анонимный подклассVocabulary
класс с методами-членами, представляющими термины в словаре, и они будут доступны для возвращаемого объекта.
Я хотел бы точно понять, что я делаю, поэтому у меня есть пара вопросов. Во-первых, каков тип возврата наfoo
метод на самом деле для? Это просто для (необязательно) документации? Это явно ограничивает тип возвращаемого значения (например, я не могу изменить его наInt
в этом случае), и если я удаляю это полностью, я получаю ошибку как это:
scala> FooExample.foo
<console>:8: error: type mismatch;
found : Bar
required: Nothing
FooExample.foo
^
Но яМожно изменить наAny
и до сих пор получить статически типизированныйBar
когда я звонюfoo
.
Во-вторых, это поведение указано где-то? Это кажется довольно элементарным набором вопросов, но я не смог найти четкого объяснения или обсуждения.