Scala 宏:使用准引号访问成员

2023-12-26

我正在尝试实现一个隐式物化器,如下所述:http://docs.scala-lang.org/overviews/macros/implicits.html http://docs.scala-lang.org/overviews/macros/implicits.html

我决定创建一个宏,将案例类从案例类转换为案例类String使用准引用进行原型设计。例如:

case class User(id: String, name: String)
val foo = User("testid", "foo")

转换foo文本应该导致"testid foo"反之亦然。

这是我创建的简单特征及其伴随对象:

trait TextConvertible[T] {
  def convertTo(obj: T): String
  def convertFrom(text: String): T
}

object TextConvertible {
  import language.experimental.macros
  import QuasiTest.materializeTextConvertible_impl
  implicit def materializeTextConvertible[T]: TextConvertible[T] = macro materializeTextConvertible_impl[T]
}

这是宏:

object QuasiTest {
  import reflect.macros._

  def materializeTextConvertible_impl[T: c.WeakTypeTag](c: Context): c.Expr[TextConvertible[T]] = {
    import c.universe._
    val tpe = weakTypeOf[T]

    val fields = tpe.declarations.collect {
      case field if field.isMethod && field.asMethod.isCaseAccessor => field.asMethod.accessed
    }

    val strConvertTo = fields.map {
      field => q"obj.$field"
    }.reduce[Tree] {
      case (acc, elem) => q"""$acc + " " + $elem"""
    }

    val strConvertFrom = fields.zipWithIndex map {
      case (field, index) => q"splitted($index)"
    }

    val quasi = q"""
      new TextConvertible[$tpe] {
        def convertTo(obj: $tpe) = $strConvertTo
        def convertFrom(text: String) = {
          val splitted = text.split(" ")
          new $tpe(..$strConvertFrom)
        }
      }
    """

    c.Expr[TextConvertible[T]](quasi)
  }
}

这会产生

{
  final class $anon extends TextConvertible[User] {
    def <init>() = {
      super.<init>();
      ()
    };
    def convertTo(obj: User) = obj.id.$plus(" ").$plus(obj.name);
    def convertFrom(text: String) = {
      val splitted = text.split(" ");
      new User(splitted(0), splitted(1))
    }
  };
  new $anon()
}

生成的代码看起来不错,但我收到了错误value id in class User cannot be accessed in User在编译时尝试使用宏。

我怀疑我使用了错误的字段类型。我试过field.asMethod.accessed.name,但结果是def convertTo(obj: User) = obj.id .$plus(" ").$plus(obj.name );(注意后面的多余空格id and name),这自然会导致错误value id is not a member of User.

我究竟做错了什么?


啊,在发出我的问题后几乎立即就明白了。

我改变了线路

val fields = tpe.declarations.collect {
  case field if field.isMethod && field.asMethod.isCaseAccessor => field.asMethod.accessed
}

to

val fields = tpe.declarations.collect {
  case field if field.isMethod && field.asMethod.isCaseAccessor => field.name
}

这解决了问题。

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

Scala 宏:使用准引号访问成员 的相关文章

随机推荐

  • GITLAB CI 管道未触发

    我已经为 GitLab CI CD 编写了这个 yml 文件 有一个已配置并正在运行的共享运行器 我是第一次这样做 不确定我哪里出错了 我正在进行的 Angular JS 项目 存储库上有一个 gulp 构建文件 并且在本地计算机上完美运行
  • 正则表达式 - 替换除 URL/URI 内的单词

    为 Web 应用程序编写全球化模块 我需要一个正则表达式来用另一个单词 翻译 替换一个单词的所有实例 除了在 URL URI 中找到的单词 编辑 我忘了提及我正在使用 Ruby 所以我不能使用 Lookbehind 根据 URI 正则表达式
  • 当前上下文中不存在错误但编译正常

    我遇到了一个我认为有点奇怪的问题 我收到两个 当前上下文中不存在 错误 Error 1 The name employeeDetails does not exist in the current context c users kelly
  • Qt/QML:将 QImage 从 C++ 发送到 QML 并在 GUI 上显示 QImage

    我创建了一个类Publisher它周期性地发出QImage目的 然而我很难画出QImage到 QML 元素 看来Image and CanvasQML 组件需要QUrl代替QImage 但我不知道如何转换我的QImage to a QUrl
  • 使用 ffmpeg 和 xfade 过滤器合并多个视频文件[关闭]

    Closed 这个问题是与编程或软件开发无关 help closed questions 目前不接受答案 我需要将多个视频文件 包含音频 合并到一个视频中 我注意到 xfade 最近发布并使用了它 但我遇到了音频同步问题 所有视频的视频和音
  • UWP/WinRT:如何保存然后恢复简单的文本框以从终止状态恢复?

    In 这个文件 https msdn microsoft com en us library windows apps xaml mt243287 aspx在描述 Windows 10 UWP 应用程序的生命周期时 它指出 用户现在希望您的
  • 为什么 Jupyter 寻找我尚未安装的扩展?

    即使在完全原始的虚拟环境中 我也会收到以下形式的错误 Package jupyter server terminals took 0 0020s to import W 2023 09 14 09 17 01 917 ServerApp N
  • 使用 php SOAP 和 WSDL 的正确步骤是什么?

    我已经解决了许多问题和困惑 请参阅 关于此问题的最终代码和问题 https stackoverflow com questions 27147950 soap issue server was unable to process reque
  • Bootstrap 3 带有输入组的验证状态

    如何将 Bootstrap 3 验证状态添加到输入组 该状态似乎仅适用于组的输入部分 编辑 10 02 2014 为了澄清 我使用带有按钮的输入组 div class form group has success col md 3 div
  • C++ 错误 - C4819、C2761、C2447

    我正在使用 Visual Studio 2017 来了解 SFML 和精灵动画 但我无法运行此代码 我用编码 Unicode 带有签名的UTF 8 代码页65001 保存它 include
  • C中的字符数组消隐

    code int main int n m i j char a 10 10 printf enter n and m values n scanf d d n m printf enter array values for i 0 i
  • Webpack UMD:关键依赖项...无法静态提取

    我正在尝试使用 webpack 构建一个 umd 库 无论我做什么都会收到警告 D Code Node sample io source index ts 中的警告 3 24 关键依赖 require函数的使用方式无法静态提取依赖 当我尝试
  • 访问远程服务器时MySQL连接出错

    I ve 托管 MySQL 数据库 in a 网络服务器 I ve 授予所有权限并允许我的IP远程连接到这个数据库从我的本地计算机 它已连接 我可以将数据从数据库检索到我的 Java Swing 应用程序 但是有时我收到此错误消息 and
  • 自定义鸭子类型的 Python 类型注释

    蟒蛇的typing模块定义了许多鸭子类型 例如 typing SupportsAbs表示任何实现了 abs 特殊方法 是否可以以某种方式定义自定义鸭子类型 以便我可以将它们用作有效的类型注释 例如 我希望能够注释一个参数应该是一个鸭子类型的
  • 使用 Ajax 从实时 PHP 和 Python 输出更新页面内容

    老用户 第一次提问 我从社区学到了很多东西 我喜欢这个网站 这就是我拍摄的目的 我想要一个在后端运行 ping 命令的 Web 界面 理想情况下 我想要一个网站 该网站具有允许您输入 IP 地址或域的文本输入 运行命令的按钮以及从 PHP
  • 批处理 - 将变量转换为大写

    我将如何改变destl变量在使用前转换为大写 我假设某种角色交换 但我无法让它工作 代码如下 echo off echo set P destf Enter First Name set P destl Enter Last Name se
  • 如何从youtubeApi v3中的VideoId android获取youtube视频的评论?

    我看过了Youtube API v3 https developers google com youtube v3 docs videos对于Android 我可以获得有关的大部分信息Youtube Video via Video Id 然
  • 解析错误:语法错误,意外的 T_FUNCTION 第 10 行?

    我的代码有什么问题吗 我在测试服务器上运行了代码并且代码有效 但是当我将其上传到生产服务器时 我得到了 Parse error syntax error unexpected T FUNCTION in hermes bosweb web0
  • 关于c#中隐式运算符重载的问题

    MyClass c 10 有什么办法可以让这段代码工作吗 我知道通过隐式运算符重载 您可以得到相反的结果 int i instanceOfMyClass Thanks Sure class MyClass public static imp
  • Scala 宏:使用准引号访问成员

    我正在尝试实现一个隐式物化器 如下所述 http docs scala lang org overviews macros implicits html http docs scala lang org overviews macros i