开发者

Scala - omit parentheses from apply method for a DSL

开发者 https://www.devze.com 2023-03-21 21:16 出处:网络
I\'m trying to create a DSL and running into a problem.I have these definitions: case class Var(name: String)

I'm trying to create a DSL and running into a problem. I have these definitions:

case class Var(name: String)
case class Lam(v: Var, t开发者_运维问答: Var)
val (a, b) = (Var("a"), Var("b"))

I want to be able to do this:

scala> \ a b
Lam(Var(a),Var(b))

Reading up on the rules of parenthesis dropping, I see that I need to chain functions that take one parameter each, so I've created a series of "builder" classes that perform the construction:

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

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

val \ = new LamBuilderA

I had hoped this would work since each apply takes only one argument. But, it doesn't seem like dropping the parentheses is legal for apply since it wants to treat the argument as a method name:

scala> \(a)(b)
res95: Lam = Lam(Var(a),Var(b))

scala> \ a b
error: value a is not a member of LamBuilderA
    \ a b
      ^

Any ideas how how I can get the DSL syntax without parentheses?

Bonus Question: Can I get this?:

scala> \a.b
Lam(Var(a),Var(b))


You can get pretty close using one of 4 unary prefix operators (~, !, +, -):

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))
0

精彩评论

暂无评论...
验证码 换一张
取 消