斯卡拉树比赛案例
我是
Scala的新手,对于编写宏并寻找一些帮助/建议非常陌生.我有以下代码……
trait ValidationRule case class Required() extends ValidationRule case class HasLength(l: Int) extends ValidationRule case class Person(name: String) myMacro[Person] { p => p.name.is(Required(),HasLength(255)) } 显然这里有一些丢失的代码,但这只是伪问题. 所以给定一个代表p =>的树. p.name.is(Required(),HasLength(255))我正在尝试编写一个匹配/大小写来选择代表ValidationRule的所有表达式.就像是: case TypeApply(Select(_,.... 任何人都可以提出最佳匹配案例,以便能够从“is”方法中提取代表每个“所有”ValidationRules的树列表吗? 解决方法
你一定要看看
Quasiquotes.
Quasiquotes用于做两件事:构建树,以及模式匹配树.它们允许您根据等效的Scala代码表达要使用的树.你让quasiquote库处理Scala代码映射到Tree图的方式,这是一件好事! 您可以在REPL中使用它们,尽管宏结构中的结果可能略有不同: scala> import scala.reflect.runtime.universe._ scala> showRaw(cq"p => p.name.is(Required(),HasLength(255))") res0: String = CaseDef( Bind( TermName("p"),Ident(termNames.WILDCARD)),EmptyTree,Apply( Select( Select( Ident(TermName("p")),TermName("name")),TermName("is")),List( Apply( Ident(TermName("Required")),List()),Apply( Ident(TermName("HasLength")),List(Literal(Constant(255))))))) 你可以用Quasiquotes做的另一件事是实际使用它们进行模式匹配. scala> val fromTree = cq"p => p.name.is(Required(),HasLength(255))" scala> val cq"p => p.name.is($x,$y)" = fromTree x: reflect.runtime.universe.Tree = Required() y: reflect.runtime.universe.Tree = HasLength(255) 现在,您必须要小心,因为如果用户将其模式变量命名为p,则该模式仅匹配. scala> val fromTree = cq"x => x.name.is(Required(),$y)" = fromTree scala.MatchError: case (x @ _) => x.name.is(Required(),HasLength(255)) (of class scala.reflect.internal.Trees$CaseDef) ... 33 elided 相反,你会想要更通用一点: scala> val cq"${p1:TermName} => ${p2:TermName}.name.is($x,$y)" = fromTree p1: reflect.runtime.universe.TermName = x p2: reflect.runtime.universe.TermName = x x: reflect.runtime.universe.Tree = Required() y: reflect.runtime.universe.Tree = HasLength(255) scala> p1 == p2 res2: Boolean = true 当然,如果您在模式匹配中执行此操作,则可以执行以下操作: case cq"${p1:TermName} => ${p2:TermName}.name.is($x,$y)" if p1 == p2 => ??? 请记住,宏是一个深洞,黑洞.如果您刚开始使用,则需要花费大量时间来使宏代码正确无误.在此之后,期望花费大量时间处理边缘情况. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |