我们现在非常熟悉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)
。此外,当用户以这种方式创建大量对象时,情况可能确实如此。我只是不知道这是否有效,所以如果你能告诉我价值课程涵盖了这种情况 - 我很高兴知道这一点。
答案 0 :(得分:3)
回到当天(2.10.0-RC1)我在使用宏的隐式类时遇到了麻烦(对不起,我不记得原因)但解决方法是使用:
以下内容可能适合您:
implicit def toNonsense(s:String): Nonsense = macro ...
...
class Nonsense(...){
...
def @@(...):... = macro ...
...
}
实施起来非常痛苦。话虽如此,宏以来变得更容易实现。
如果你想查看我做了什么,因为我不确定这适用于你想做什么,请参考this excerpt of my code(非惯用风格)。
我不会在这里解决它的相关性,因为它已被其他人评论过。