是否可以定义带有可变参数的宏,并获取每个参数的类型?

2024-04-13

下面是一个明显的可变参数函数:

def fun(xs: Any*) = ???

我们可以用类似的方式定义一个宏:

def funImpl(c: Context)(xs: c.Expr[Any]*) = ???

fun(1,"1",1.0)

但在本例中,所有参数都键入为Any。事实上,编译器在编译时就知道类型,但对我们隐藏了。是否可以获得参数列表and它们在宏中的类型?


当然可以——例如:

import scala.language.experimental.macros
import scala.reflect.macros.Context

object Demo {
  def at(xs: Any*)(i: Int) = macro at_impl
  def at_impl(c: Context)(xs: c.Expr[Any]*)(i: c.Expr[Int]) = {
    import c.universe._

    // First let's show that we can recover the types:
    println(xs.map(_.actualType))

    i.tree match {
      case Literal(Constant(index: Int)) => xs.lift(index).getOrElse(
        c.abort(c.enclosingPosition, "Invalid index!")
      )
      case _ => c.abort(c.enclosingPosition, "Need a literal index!")
    }
  }
}

进而:

scala> Demo.at(1, 'b, "c", 'd')(1)
List(Int(1), Symbol, String("c"), Char('d'))
res0: Symbol = 'b

scala> Demo.at(1, 'b, "c", 'd')(2)
List(Int(1), Symbol, String("c"), Char('d'))
res1: String = c

请注意,推断的类型是精确且正确的。

另请注意,如果参数是带有以下内容的序列,则这将不起作用_*当然,如果您想捕获这种情况并提供有用的错误消息,则需要编写类似以下内容的内容:

def at_impl(c: Context)(xs: c.Expr[Any]*)(i: c.Expr[Int]) = {
  import c.universe._

  xs.toList.map(_.tree) match {
    case Typed(_, Ident(tpnme.WILDCARD_STAR)) :: Nil => 
      c.abort(c.enclosingPosition, "Needs real varargs!")
    case _ =>
      i.tree match {
        case Literal(Constant(index: Int)) => xs.lift(index).getOrElse(
          c.abort(c.enclosingPosition, "Invalid index!")
        )
        case _ => c.abort(c.enclosingPosition, "Need a literal index!")
      }
  }
}

看我的问题here https://stackoverflow.com/q/13663216/334519和错误报告here https://issues.scala-lang.org/browse/SI-6777进行更多讨论。

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

是否可以定义带有可变参数的宏,并获取每个参数的类型? 的相关文章

随机推荐

  • 复制构造函数初始化列表

    我知道 如果您将某个成员保留在无参数构造函数的初始化列表之外 则将调用该成员的默认构造函数 复制构造函数是否同样调用成员的复制构造函数 还是也调用默认构造函数 class myClass private someClass a someOt
  • 有没有Delphi DFM 到Delphi 源代码的转换工具?

    Delphi 表单设计器非常好 但我们需要直接从源代码开始工作 是否有工具或脚本可以获取一批 DFM 文件并将它们转换为 Delphi 源代码 您可以使用ComponentsToCode函数来自GExperts http www gexpe
  • 我需要 log4j 1.2 和 2.5 共存于同一个 web 应用程序中

    我有一个 java web 应用程序 它使用 Crystal 的 Business Objects 运行时来运行以该技术编码的报告 问题在于 Crystal 的猴子直接引用了 log4j 1 2 类中的方法 此方法不是 log4j 1 2
  • 等待(长超时)和加入(长毫秒)之间的区别?

    当线程 1 在线程 2 上调用 wait 和 join 方法时 线程 1 会等待线程 2 一段时间或直到线程 2 完成 如果我们使用这些方法的重载版本 即 wait long timeout 和 join long millis 那么 在
  • 如何在 Sublime Text 2 中插入一列递增的数字?

    text text text text 编辑后 这些文本变成 1 text 2 text 3 text 4 text 在 Notepad 中使用列编辑器很容易 但我不知道如何在 Sublime Text 2 中做同样的事情 The 文字糕点
  • 使用 C# 访问 Sharepoint - 在哪里可以找到参考库?

    我目前正在用 C 编写一个 Windows 应用程序 它将向文档库列表添加文档 我试图引用 Microsoft Sharepoint 但是我没有看到 Visual Studio 2005 添加引用列表中的 COM 或 NET 库 我需要引用
  • Mac OS 上的 Ada 编译器 GNAT

    我正在尝试使用 mac 上的终端编译 ada 但总是收到此错误 错误 x ada 中的 ada 值无效 有人知道如何解决这个问题吗 你可能没有安装Ada编译器 OSX自带的gcc不支持Ada 目前 有两种适用于 OSX 且支持 Ada 的免
  • css-显示页脚下方有大量空间

    请参阅此链接中的图像 https docs google com document d 1r9L9eLBddMOdHAP3KfAx8ND SF8b8zBl53o88aUbHT4 edit pli 1 https docs google co
  • 核心蓝牙发送数据包时速度变慢

    我遇到一个问题 即使用 peripheral writeValue dataPacket forCharacteristic writeChar type CBCharacteristicWithResponse 并且 iOS 设备实际物理
  • 如何使用 Swift 函数返回的值

    我正在尝试使用 Swift 函数将一个圆放置在视图的中心 这样无论屏幕大小如何 它始终位于中心 我可以在由一组任意 x 和 y 值定义的点处绘制圆 但我需要函数来提供这些值 我创建了一个名为的函数screenCentre 读取并返回两个参数
  • 未捕获(承诺):错误:StaticInjectorError(AppModule)[选项]

    我有一个奇怪的错误 通常 我用谷歌搜索过 在这种错误情况下 Angular 在方括号中指定到底是哪个模块 服务 提供者 等导致了问题 然而这里只说options 我尝试添加HttpClientModule HttpModule Option
  • 关联来自不同数据库的表 - 实体框架

    我想知道如何 如果可能 使用实体框架关联来自不同数据库的表 我有一个 edmx 用于我的 xyz 数据库 另一个用于我的 abc 数据库 我需要使用 EF 将它们关联起来 我知道如何使用 FK 修复此问题 但这不是我想要的 我希望能够使用可
  • 检测服务器/站点对跨域 XMLHttpRequest 的支持吗?

    我有兴趣看看最小的跨浏览器 Javascript 代码 jQuery 也很好 可以用来验证我希望发送跨域 AJAX 请求的网站是否支持CORS http en wikipedia org wiki Cross origin resource
  • 如何创建包含字符串字符的列表? [复制]

    这个问题在这里已经有答案了 是否可以将字符串转换为列表 如下所示 5 6 into 5 6 list 5 6 returns 5 6
  • Julia:显示函数体(以查找丢失的代码)

    在 R 语言中 我可以声明一个函数并查看函数体 如下所示 gt megafoobar function x return x 10000 gt body megafoobar return x 10000 类似的事情在 Julia 中也可能
  • Scala 中的通配符导入对于增量编译是否不好?

    在 Scala 中 从增量编译器 sbt Eclipse 中的 sbt IntelliJ 的功效和速度的角度来看 使用通配符导入是否不好 它是否会对这些增量编译器在发生更改时决定重新编译内容的方式产生不利影响 例如 如果对于一个新班级X 我
  • 在 Julia 中有效求解特定线性系统

    我广泛使用朱莉娅的线性方程求解器res X b 由于参数变化 我必须在程序中使用它数百万次 这工作正常 因为我使用的是小尺寸 最多30 现在我想分析更大的系统 最多1000 线性求解器不再有效 我认为可以有一个解决办法 然而我必须说 有时我
  • 在 Netsuite 中按自定义字段搜索客户

    我能够使 api 在 php 中工作并通过内部 ID 搜索客户 不过 我有一个场景 我将通过自定义字段搜索客户 在 客户 下 它有一个自定义选项卡 其中包含多个域名和域详细信息 例如 主要搜索条件 域名 这在 netsuite php ap
  • Visual Studio 2012(RTM,在 Windows 8 RTM 上)中没有带断点的 XAML 绑定调试?

    将我的 Silverlight 5 解决方案升级到 Visual Studio 2012 RTM 然后更新到 Windows 8 RTM 后 我注意到当您在 XAML 中设置断点时 您会在调试模式下看到以下工具提示 当前不会命中断点 找不到
  • 是否可以定义带有可变参数的宏,并获取每个参数的类型?

    下面是一个明显的可变参数函数 def fun xs Any 我们可以用类似的方式定义一个宏 def funImpl c Context xs c Expr Any fun 1 1 1 0 但在本例中 所有参数都键入为Any 事实上 编译器在