5

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

括弧の削除のルールを読んで、それぞれ1つのパラメーターを受け取る関数をチェーンする必要があることがわかったので、構築を実行する一連の「ビルダー」クラスを作成しました。

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

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

val \ = new LamBuilderA

applyそれぞれが1つの引数しかとらないので、これが機能することを望んでいました。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))
4

1 に答える 1

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))
于 2011-07-21T18:37:38.427 に答える