【问题标题】:Scala - omit parentheses from apply method for a DSLScala - 从 DSL 的应用方法中省略括号
【发布时间】:2011-07-21 17:37:14
【问题描述】:

我正在尝试创建 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))

【问题讨论】:

  • 我当然希望你不能得到\a.b!重载 . 并不是我认为的嵌入式 DSL 的好主意。

标签: scala dsl apply


【解决方案1】:

您可以使用 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))

【讨论】:

  • 感谢这个有趣的答案。我想我将不得不坚持使用 \(a,b) 作为我的语法,但利用一元运算符是个好主意。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多