Tra*_*own 41 macros types scala scala-2.10 scala-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)
}
Run Code Online (Sandbox Code Playgroud)
我已经说了三次我想要foo返回一个Foo,但我可以做以下(在2.10.0-RC3中):
scala> FooExample.foo
res0: Bar = Bar@4118f8dd
scala> res0.launchMissiles
res1: String = launching
Run Code Online (Sandbox Code Playgroud)
如果我删除任何一个上的类型参数,也会发生同样的事情c.Expr.如果我真的想确保无论谁打电话foo都看不到他们正在获得Bar,我必须在树本身添加类型归属.
这实际上非常棒 - 例如,我可以将宏指向某种类型的模式,并Vocabulary使用表示词汇表中的术语的成员方法创建某个类的匿名子类,这些将在返回的对象上可用.
我想知道我到底在做什么,所以我有几个问题.首先,该foo方法实际上的返回类型是什么?它是否仅适用于(可选)文档?它明确地约束了返回类型(例如,Int在这种情况下我无法将其更改为),如果我将其完全删除,则会出现如下错误:
scala> FooExample.foo
<console>:8: error: type mismatch;
found : Bar
required: Nothing
FooExample.foo
^
Run Code Online (Sandbox Code Playgroud)
但我可以改变它,Any并Bar在我打电话时仍然得到一个静态类型foo.
第二,这个行为是在某处指定的吗?这似乎是一个相当基本的问题,但我无法找到明确的解释或讨论.
Eug*_*ako 21
此行为未明确但有意,但可能看起来令人困惑.我们计划详细说明返回类型在宏签名中的作用,但目前我觉得灵活性是一件好事.
有时行为也是不一致的,例如当宏被类型推断中间捕获时,将使用其静态签名(即Foo在您的示例中),而不是实际扩展的类型.这是因为宏扩展被有意地延迟,直到完成类型推断(这样宏实现才能看到推断类型,而不是类型变量).这是一个权衡,不一定是最好的,所以我们计划很快重新审视它:https://issues.scala-lang.org/browse/SI-6755.
这个部门的另一个问题是隐式宏.当隐式宏的返回类型是通用的并且需要从所请求的隐式值的类型推断时,会发生不好的事情.这使得目前无法使用宏来生成类型标记:https://issues.scala-lang.org/browse/SI-5923.
| 归档时间: |
|
| 查看次数: |
3537 次 |
| 最近记录: |