Scala DSL:如何添加 "nothing" 的单词?

Scala DSL: How to add words that do "nothing"?

我尝试在 Int 上构建一个简单的隐式 class 来为 Ints 添加一个函数:

object Helper {
  implicit class IntHelper(i: Int) {
    def add(str: String): Int = i + str.toInt
  }
}

为了写得更自然,我希望 DSL 允许这样做(import Helper._):

2 add "3" and add "4"

但我不知道如何执行 and 功能。我认为这个会起作用:

object Helper {
  implicit class IntHelper(i: Int) {
    def add(str: String): Int = i + str.toInt
    def and: Int = i
  }
}

但是如果没有括号它就不能工作(事实上,"2.add("3").and.add("4") 可以工作但是我觉得 DSL 的句号和括号太多了)。

谢谢

问题在于 and 现在用作后缀表示法,通常不建议这样做,因为它恰好创建了 problem with delimiting the expression。所以你可以写

(2 add "3" and) add "4"

但是

2 add "3" and add "4"

大致解析为

2.add("3").and(add)."4"

我会反对这样的 DSL。尤其是当刚接触 Scala 时,人们对 Scala 允许此类 DSL 的表现力很感兴趣,但你必须认真质疑它们的价值所在。


如果你真的想走这条路,你可以通过将虚拟 and 方法从后缀变为中缀,添加另一个虚拟参数,例如then:

object Helper {
  implicit class IntHelper(i: Int) {
    def add(str: String): Int = i + str.toInt
  }

  implicit class AndThen[A](in: A) {
    def and(t: then.type): A = in
  }

  object then
}

import Helper._

2 add "3" and then add "4"

问题正如0__所述。除了 0__ 的解决方案之外,我还没有看到如何在没有括号的情况下完全实现这一目标的方法。

作为替代方案,这里有一个版本只需要在链式 add 调用周围加上括号,比原来的解决方案要少,而且不需要额外的关键字:

object Helper {
  implicit class IntHelper(i: Int) {
    def add(str: String): Int = i + str.toInt
    def and(add: AddWord): Int = i + add.str.toInt
  }

  val add = AddWord
  case class AddWord(private[Helper] val str: String)
}

可用作:

import Helper._
1 add "3" and add("4") and add("5")