Scala - 从DSL的apply方法中省略括号

dhg*_*dhg 4 dsl scala apply

我正在尝试创建一个DSL并遇到问题.我有这些定义:

case class Var(name: String)
case class Lam(v: Var, t: Var)
val (a, b) = (Var("a"), Var("b"))
Run Code Online (Sandbox Code Playgroud)

我希望能够这样做:

scala> \ a b
Lam(Var(a),Var(b))
Run Code Online (Sandbox Code Playgroud)

阅读括号删除规则,我发现我需要链接每个都带有一个参数的函数,所以我创建了一系列执行构造的"构建器"类:

class LamBuilderB(v: Var) {
    def apply(t: Var) = Lam(v, t)
}

class LamBuilderA {
    def apply(v: Var) = new LamBuilderB(v)
}

val \ = new LamBuilderA
Run Code Online (Sandbox Code Playgroud)

我曾希望这会有效,因为每个人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
      ^
Run Code Online (Sandbox Code Playgroud)

有没有想法如何在没有括号的情况下获得DSL语法?

奖金问题:我能得到这个吗?:

scala> \a.b
Lam(Var(a),Var(b))
Run Code Online (Sandbox Code Playgroud)

Vas*_*iuk 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))
Run Code Online (Sandbox Code Playgroud)