Scala 宏的静态返回类型

2024-03-16

所以我有这个宏:

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
                         ^

But I can将其更改为Any并且仍然得到静态类型Bar当我打电话时foo.

其次,这种行为是否在某处指定?这似乎是一组相当基本的问题,但我无法找到明确的解释或讨论。


此行为未指定但有意为之,尽管它可能看起来令人困惑。我们计划详细说明返回类型在宏签名中的作用,但目前我觉得灵活性是一件好事。

有时行为也不一致,例如当宏陷入类型推断过程中时,将使用其静态签名(即Foo在您的示例中),而不是实际扩展的类型。这是因为宏扩展被故意延迟,直到类型推断完成(以便宏实现看到推断的类型,而不是类型变量)。这是一种权衡,不一定是最好的,所以我们计划很快重新审视它:https://issues.scala-lang.org/browse/SI-6755 https://issues.scala-lang.org/browse/SI-6755.

该部门的另一个问题是隐式宏。当隐式宏的返回类型是通用的并且需要从隐式值的请求类型推断时,就会发生不好的事情。这使得目前无法使用宏来生成类型标签:https://issues.scala-lang.org/browse/SI-5923 https://issues.scala-lang.org/browse/SI-5923.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Scala 宏的静态返回类型 的相关文章

随机推荐