是否可以通过宏实现隐式类提供的功能?

时间:2014-05-02 00:36:21

标签: scala scala-macros

我们现在非常熟悉Scala中的暗示,但宏是非常未被发现的区域(至少对我而言),尽管Eugene Burmako出现了一些很棒的文章,但它仍然不是一个简单的材料

在这个特定的问题中,我想知道是否有可能仅使用宏来实现类似于以下代码功能:

implicit class Nonsense(val s: String) {
  def @@(i:Int) = s.charAt(i)
}

例如,"asd" @@ 0将返回'a'。我可以实现使用中缀表示法的宏吗?这样做的原因是我正在为一些已经存在的项目编写一个DSL,并且允许使API清晰简洁,但每当我编写一个新的隐式类时,我都想引入一个新的减速因子。是的,我确实知道值类和东西,我认为如果我的DSL在编译期间而不是在运行时转换为底层库API调用,那将会非常棒。

TL; DR:我可以在不更改API的情况下用宏替换implicits吗?我可以用中缀形式编写宏吗?有没有更适合这种情况的东西?麻烦值得吗?

UPD。对那些提倡价值观的人来说:在我的情况下,我只有一个简单的包装器 - 它们经常堆叠在一起。例如,我有一个隐式类,它接受一些参数,返回一个包装这个参数的lambda(即部分函数),以及专门用于包装这种类型函数的第二个隐式类。我可以做到这样的事情:

a --> x ==> b

其中第一个类包装a并添加-->方法,第二个包装返回类型a --> x并定义==>(b)。此外,当用户以这种方式创建大量对象时,情况可能确实如此。我只是不知道这是否有效,所以如果你能告诉我价值课程涵盖了这种情况 - 我很高兴知道这一点。

1 个答案:

答案 0 :(得分:3)

回到当天(2.10.0-RC1)我在使用宏的隐式类时遇到了麻烦(对不起,我不记得原因)但解决方法是使用:

  • 要转换为类的隐式def宏
  • 将中缀运算符定义为该类
  • 中的def宏

以下内容可能适合您:

implicit def toNonsense(s:String): Nonsense = macro ...
...
class Nonsense(...){
  ...
  def @@(...):... = macro ...
  ...
}

实施起来非常痛苦。话虽如此,宏以来变得更容易实现。

如果你想查看我做了什么,因为我不确定这适用于你想做什么,请参考this excerpt of my code(非惯用风格)。

我不会在这里解决它的相关性,因为它已被其他人评论过。