【发布时间】:2018-01-26 08:57:43
【问题描述】:
我想创建一个宏,该宏生成类似于访问者模式的案例类实例树的递归遍历。生成的代码应针对其类型派生自多种基类型之一的所有字段进行递归。
我想到了一些可以类似这样使用的代码:
trait A
trait B
trait C
case object D extends A { }
case object E extends C { }
case class F (a: A, b: B, c: Int) extends A
case class G (d: C, e: String) extends B
val instanceOfA = F (D, G (E, "Foo"), 1)
// expected type extra types that should be included in traversal
// vv vv
traverse[A, B, C] (handlerForA, handlerForB, handlerForC) (instanceOfA)
遍历的类型类似于以下(我知道这不是有效的语法,但想不出更好的语法):
def traverse[T, U...] (handleT : T => Unit, handleU... : U... => Unit) : T => Unit = macro traverseImpl
我知道 Scala 不支持可变参数泛型,但我不明白为什么不应该有一种方法可以用宏来实现这样的事情。但是我还没有找到一种方法可以将多种类型作为参数传递给 def 宏。
【问题讨论】:
-
你真的不需要像光学这样的东西吗:julien-truffaut.github.io/Monocle ?
-
我的意思是:将每个类的处理程序与每个嵌套级别的镜头提取器组合起来,您应该获得相同的结果,尽管语法略有不同。
-
感谢您的提示。 Monocle 看起来很有趣,它甚至可以支持创建已编辑的实例。我想知道它是否可以提供足够的灵活性和性能来在我相当复杂的场景中工作而无需太多开销。
-
一个问题:你想分支吗(例如,对于 F,你想同时遍历 A 和 B)吗?我正在考虑为体育起草一个实施方案,所以根据情况我会采取不同的方法。
-
是的,我会一次遍历它们,因为我可以进行包含多种类型的递归,例如
case class H (a: A) extends B; object I extends B; F (H (F (F (D, I, 0), I, 1)), I, 2),我希望能够一次更改所有F.cs。
标签: scala generics macros tree-traversal scala-macros