Więc mam tego makra:statyczny typ powrót Scala makropolecenia
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)
}
mówiłem trzy razy, że chcę foo
zwrócić Foo
, a jednak mogę wykonać następujące czynności (w 2.10. 0-RC3):
scala> FooExample.foo
res0: Bar = [email protected]
scala> res0.launchMissiles
res1: String = launching
To samo dzieje się, jeśli mogę usunąć parametry typu na obu c.Expr
. Jeśli naprawdę chcę się upewnić, że ktokolwiek dzwoni pod numer foo
, nie może zobaczyć, że uzyskuje on Bar
, muszę dodać przypisanie typu w drzewie.
Jest to całkiem niezłe - oznacza to na przykład, że mogę wskazać makro na schemacie i stworzyć anonimową podklasę klasy Vocabulary
z metodami reprezentującymi terminy w słowniku, a te będą dostępne na zwrócony obiekt.
Chciałbym zrozumieć, co dokładnie robię, więc mam kilka pytań. Po pierwsze, jaki jest rzeczywiście typ zwrotu w metodzie foo
? Czy jest on dostępny tylko dla (opcjonalnej) dokumentacji? To wyraźnie ogranicza typ zwracany (np, nie mogę go zmienić na Int
w tym przypadku), a jeśli usunąć go w całości pojawia się błąd jak poniżej:
scala> FooExample.foo
<console>:8: error: type mismatch;
found : Bar
required: Nothing
FooExample.foo
^
Ale można zmienić go naAny
i nadal otrzymuję statycznie wpisany Bar
, gdy zadzwonię pod numer foo
.
Po drugie, czy to zachowanie jest gdzieś określone? Wydaje się, że jest to dość elementarny zestaw problemów, ale nie byłem w stanie wyszukać jasnego wyjaśnienia lub dyskusji.
@ som-snytt: Ale nadal oczekiwałbym typu zwrotu na 'foo', aby mieć ostatnie słowo (chociaż cieszę się, że tak nie jest). –
Adnotacja typu zwrotu na 'FooExample.foo' jest tutaj bardzo dziwna. W przeciwnym razie spodziewam się zachowania makr. – drstevens
@drstevens: Zgoda. –