我正在尝试创建DSL并遇到问题。我有这些定义:
case class Var(name: String)
case class Lam(v: Var, t: Var)
val (a, b) = (Var("a"), Var("b"))
我希望能够做到这一点:
scala> \ a b
Lam(Var(a),Var(b))
阅读括号删除的规则,我看到我需要链接每个都带有一个参数的函数,所以我创建了一系列执行构造的“构建器”类:
class LamBuilderB(v: Var) {
def apply(t: Var) = Lam(v, t)
}
class LamBuilderA {
def apply(v: Var) = new LamBuilderB(v)
}
val \ = new LamBuilderA
我曾希望这会有效,因为每个apply
只需要一个参数。但是,似乎放弃括号对apply
是合法的,因为它想要将参数视为方法名称:
scala> \(a)(b)
res95: Lam = Lam(Var(a),Var(b))
scala> \ a b
error: value a is not a member of LamBuilderA
\ a b
^
如何在没有括号的情况下获取DSL语法的任何想法?
奖金问题:我可以得到这个吗?:
scala> \a.b
Lam(Var(a),Var(b))
答案 0 :(得分:6)
使用4个一元前缀运算符(~
,!
,+
,-
)中的一个,您可以非常接近:
trait Expr {
def &(other: Expr) = Lam(this, other)
def unary_~ = this
}
case class Var(name: String) extends Expr
case class Lam(a: Expr, b: Expr) extends Expr
scala> ~ Var("a") & Var("b")
res0: Lam = Lam(Var(a),Var(b))
scala> ~ Var("a") & Var("b") & Var("c")
res1: Lam = Lam(Lam(Var(a),Var(b)),Var(c))