Scala 宏的静态返回类型 [英] Static return type of Scala macros

查看:26
本文介绍了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 中):

I've said three times that I want foo to return a Foo, and yet I can do the following (in 2.10.0-RC3):

scala> FooExample.foo
res0: Bar = Bar@4118f8dd

scala> res0.launchMissiles
res1: String = launching

如果我删除任一 c.Expr 上的类型参数,也会发生同样的事情.如果我真的想确保调用 foo 的人看不到他们正在获取 Bar,我必须在树本身中添加一个类型归属.

The same thing happens if I remove the type parameters on either c.Expr. If I really want to make sure that whoever's calling foo can't see that they're getting a Bar, I have to add a type ascription in the tree itself.

这实际上非常棒——例如,这意味着我可以将宏指向某种模式并创建某个 Vocabulary 类的匿名子类,其成员方法表示词汇表中的术语,这些将在返回的对象上可用.

This is actually pretty great—it means for example that I can point a macro at a schema of some sort and create an anonymous subclass of some Vocabulary class with member methods representing terms in the vocabulary, and these will be available on the returned object.

不过,我想确切地了解我在做什么,所以我有几个问题.首先,foo 方法的返回类型实际上是为了什么?它仅可用于(可选)文档吗?它清楚地限制了返回类型(例如,在这种情况下我不能将其更改为 Int),如果我将其完全删除,则会出现如下错误:

I'd like to understand exactly what I'm doing, though, so I have a couple of questions. First, what is the return type on the foo method actually for? Is it just available for (optional) documentation? It clearly constrains the return type (e.g., I can't change it to Int in this case), and if I remove it entirely I get an error like this:

scala> FooExample.foo
<console>:8: error: type mismatch;
 found   : Bar
 required: Nothing
              FooExample.foo
                         ^

但是当我调用 foo 时,我可以将它更改为 Any 并且仍然得到一个静态类型的 Bar.

But I can change it to Any and still get a statically typed Bar when I call foo.

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

Second, is this behavior specified somewhere? This seems like a fairly elementary set of issues, but I haven't been able to search up a clear explanation or discussion.

推荐答案

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

This behavior is underspecified but intended, though it might appear confusing. We plan to elaborate on the role of return type in macro signatures, but at the moment I feel like the flexibility is a good thing to have.

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

Also at times the behavior is inconsistent, e.g. when the macro is caught in the middle of type inference, its static signature will be used (i.e. Foo in your example), not the type of the actual expansion. That's because macro expansion is intentionally delayed until type inference is done (so that macro implementations get to see inferred types, not type vars). This is a trade-off and not necessarily the best one, so we're planning to revisit it soon: https://issues.scala-lang.org/browse/SI-6755.

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

Another problem in this department is with implicit macros. When the return type of an implicit macro is generic and needs to be inferred from the requested type of an implicit value, bad things happen. This makes it currently impossible to use macros to generate type tags: https://issues.scala-lang.org/browse/SI-5923.

这篇关于Scala 宏的静态返回类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆