如何在 reify 子句中使用 Scala 宏中计算的类型?

2024-02-28

我一直在使用 Scala 宏,并在宏中包含以下代码:

    val fieldMemberType = fieldMember.typeSignatureIn(objectType) match {
      case NullaryMethodType(tpe)   => tpe
      case _                      => doesntCompile(s"$propertyName isn't a field, it must be another thing")
    }

    reify{
      new TypeBuilder() {
        type fieldType = fieldMemberType.type
      }
    }

正如你所看到的,我已经设法得到了c.universe.Type fieldMemberType。这表示对象中某个字段的类型。一旦我明白了,我想创建一个新的TypeBuilder具体化中的对象。TypeBuilder是一个带有抽象参数的抽象类。这个抽象参数是fieldType。我要这个fieldType是我以前发现的类型。

运行此处显示的代码会返回一个fieldMemberType not found。有什么办法可以让我得到fieldMemberType在 reify 子句中工作?


问题是你传递给的代码reify本质上将逐字放置在宏展开的位置,并且fieldMemberType在那里没有任何意义。

在某些情况下你可以使用splice将宏扩展时的表达式隐藏到正在具体化的代码中。例如,如果我们尝试创建此特征的实例:

trait Foo { def i: Int }

并且在宏展开时有这个变量:

val myInt = 10

我们可以这样写:

reify { new Foo { def i = c.literal(myInt).splice } }

这在这里不起作用,这意味着你将不得不忘记漂亮的小东西reify并手写出 AST。不幸的是,你会发现这种情况经常发生。我的标准方法是启动一个新的 REPL 并输入如下内容:

import scala.reflect.runtime.universe._

trait TypeBuilder { type fieldType }

showRaw(reify(new TypeBuilder { type fieldType = String }))

这将输出几行 AST,然后您可以将其剪切并粘贴到宏定义中作为起点。然后你摆弄它,替换如下内容:

Ident(TypeBuilder)

有了这个:

Ident(newTypeName("TypeBuilder"))

And FINAL with Flag.FINAL, 等等。我希望toStringAST 类型的方法与构建它们所需的代码更准确地对应,但您很快就会明白需要更改哪些内容。你最终会得到这样的结果:

c.Expr(
  Block(
    ClassDef(
      Modifiers(Flag.FINAL),
      anon,
      Nil,
      Template(
        Ident(newTypeName("TypeBuilder")) :: Nil,
        emptyValDef,
        List(
          constructor(c),
          TypeDef(
            Modifiers(),
            newTypeName("fieldType"),
            Nil,
            TypeTree(fieldMemberType)
          )
        )
      )
    ),
    Apply(Select(New(Ident(anon)), nme.CONSTRUCTOR), Nil)
  )
)

Where anon是您预先为匿名类创建的类型名称,并且constructor是一种方便的方法,我用它来使这种事情不那么可怕(你可以在末尾找到它的定义)这个完整的工作示例 https://gist.github.com/4249936).

现在如果我们把这个表达式包装成类似的东西this https://gist.github.com/4249936,我们可以写如下:

scala> TypeMemberExample.builderWithType[String]
res0: TypeBuilder{type fieldType = String} = $1$$1@fb3f1f3

所以它有效。我们采取了一个c.universe.Type(我从这里得到的WeakTypeTag类型参数的builderWithType,但它的工作方式与任何旧的完全相同Type)并用它来定义我们的类型成员TypeBuilder trait.

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

如何在 reify 子句中使用 Scala 宏中计算的类型? 的相关文章

随机推荐

  • 获取this.title属性的前2个字符,并调用对应的id

    我试图检索链接标题属性的前两个字符 将其存储到变量中 然后将该变量作为函数调用 在代码中 它说 s 是我想要放置该值的位置 有任何想法吗 flow click function if labelstatus 1 rmflow a weflo
  • 错误:“使用移动值”

    我目前正在学习 Rust 并且正在使用一个简单的计算器 重构时 我最终得到了如下代码 enum OptionalToken Foo Bar fn next token gt OptionalToken Read input classify
  • JavaScript:如何动态“过滤”我的对象

    我如何使用 JavaScript filter 属性作为过滤器我的 JavaScript 对象 我一直在阅读以下内容StackOverflow 帖子 https stackoverflow com questions 1694717 jav
  • 如何使用 Firefox Addon Builder 记录选定的文本?

    我遵循了几个教程但没有成功 我认为这是一个经典的例子 但我无法让它发挥作用 我可以保存我的项目 安装插件 当我选择一些文本时 我可以看到上下文菜单项 日志选择 但是当我单击它时 什么也没有发生 exports main function v
  • jquery 上下文选择器与 .find()

    什么更有效 var container container 1 var links1 container find a 2 var links2 a container 我个人比较喜欢 a container 因为看起来更好 但是它们的性能
  • Makefile `echo -n' 不起作用

    我试图让我的 Makefile 回显文本而不带尾随换行符 但我做不到 我在 OS X 上遇到了这种行为 在 Linux 上一切都按预期工作 Makefile a echo n hello b echo n hello c bin echo
  • 根据控制器响应动态更改视图部分

    我正在寻找以下场景的最佳方法建议 用户可以选择一个或多个 csv 文件进行验证 附件 1 单击 验证 按钮会执行验证代码 显示进度条 直到返回输出 返回响应可以是成功消息 也可以是选择验证的每个文件的错误详细信息 附件 2 现在可以使用 上
  • Makefile:目标依赖项 - 如何始终制作它?

    This will most probably be obvious and or a banality But since I am trying different approaches for hours without succes
  • Entity Framework 4 生成的查询正在连接完整表

    我有两个实体 Master 和Details 当我查询它们时 对数据库的查询结果是 SELECT Extent2 needed columns listed here Extent1 needed columns listed here F
  • 将自定义视图添加到工具栏

    我现在正在与 Cocoa 斗争两个小时 但没有成功 我想向工具栏添加自定义视图 因此 我向窗口添加了一个 NSToolbar 使用 IB 并添加了我的视图 效果完美 IB自动创建了一个NSToolbarItem 我按照苹果的说明进行操作 h
  • 将 Sencha Touch 与 jQuery 相结合

    我已经在 Sencha Touch 工作了几个星期 虽然这个框架非常强大 但我仍然发现它有一些难以使用的地方 特别是用于复杂嵌套 JSON 结果的 JSONP 数据存储 因此 我决定结合 jQuery 有用的 AJAX 和 JSON 函数
  • 拉直 B 样条线

    我插入了一条样条曲线 以将图像中的像素数据与我想要拉直的曲线相匹配 我不确定什么工具适合解决这个问题 有人可以推荐一种方法吗 这是我获取样条线的方法 import numpy as np from skimage import io fro
  • 有什么理由将 out 参数与 C# 7 元组返回值一起使用? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我刚刚观看了一个介绍C 7的新特性 https www youtube com watch v 5ju2MuqKf 8 除此之外 它引入了返回元
  • 内置对象/库的静态初始化顺序惨败

    如果我有一些静态初始化的变量 在main开始 我可以自由使用这些构造函数中的任何内置内容吗 例如
  • 使用php连接外部mysql数据库

    服务器之间可以连接mysql数据库吗 我的意思是 假设我在 2 个不同的托管服务上有 2 个帐户 其中一个有数据库 我想用 php 从另一个帐户连接它 当我尝试时 我收到 警告 mysql connect function mysql co
  • C++ 中的最小浮点正值

    C 中乘法逆元仍然有限的最小正值是多少 试过numeric limits
  • 在线验证antlr语法[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有谁知道是否存在某种用于antlr语法的在线测试环境 我可以在其中针对某些输入字符串验证和测试给定的语
  • (如何)我可以在 Docker 容器中运行 Windows Defender 吗?出现错误[关闭]

    Closed 这个问题是与编程或软件开发无关 help closed questions 目前不接受答案 我正在为 Windows 环境的端点笔测试实验室尝试一些选项 Docker 似乎是一个非常轻量级且易于配置的选项 然而 在这个设置中测
  • 如何在 JavaScript 或 jQuery 中进行 ping 操作?

    我想用 Javascript 创建一个类似游戏的 ping 就像 反恐精英 游戏一样 我正在对服务器 MySQL 进行 AJAX 调用 并想要计算所花费的时间 但我要么计算错误 要么对 ping 的想法有误 这是我到目前为止的代码 var
  • 如何在 reify 子句中使用 Scala 宏中计算的类型?

    我一直在使用 Scala 宏 并在宏中包含以下代码 val fieldMemberType fieldMember typeSignatureIn objectType match case NullaryMethodType tpe gt