Scalamacros的静态返回types
所以我有这个macros:
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
上的types参数。 如果我真的想要确保谁打电话给foo
看不到他们得到一个Bar
,我必须在树本身添加一个types归属。
这实际上非常棒,例如,我可以将某个macros指向某种types的模式,并使用表示词汇表中的词的成员方法创build一些Vocabulary
类的匿名子类,这些方法将在返回的对象上提供。
不过,我想明白我在做什么,所以我有几个问题。 首先, foo
方法实际返回的types是什么? 它是否可用于(可选)文档? 它显然限制了返回types(例如,在这种情况下,我不能将其更改为Int
),如果将其完全移除,则会出现如下错误:
scala> FooExample.foo <console>:8: error: type mismatch; found : Bar required: Nothing FooExample.foo ^
但是,我可以将它更改为Any
并在调用foo
时仍然可以获得静态types的Bar
。
其次,这是什么地方指定的行为? 这似乎是一个相当初级的问题,但我还没有find一个明确的解释或讨论。
这种行为是低估的,但意图,虽然它可能会出现混淆。 我们打算详细说明返回types在macros特征中的作用,但是现在我觉得灵活性是一件好事。
同样有时行为是不一致的,例如,当macros在types推断中被捕获时,它的静态签名将被使用(例如Foo
),而不是实际扩展的types。 这是因为macros扩展是故意延迟,直到types推断完成(所以macros实现可以看到推断types,而不是typesvariables)。 这是一个权衡,不一定是最好的,所以我们打算很快重新访问: https : //issues.scala-lang.org/browse/SI-6755 。
这个部门的另一个问题是隐含的macros。 当隐式macros的返回types是通用的并且需要从隐式值的请求types中推断时,会发生不好的事情。 这使得目前不可能使用macros来生成types标签: https : //issues.scala-lang.org/browse/SI-5923 。