Scala DSL:如何添加“无”的单词?

时间:2016-04-23 17:17:18

标签: scala dsl implicit

我尝试在Int上构建一个简单的隐式类来为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来说,有太多的句号和圆括号。)

由于

2 个答案:

答案 0 :(得分:5)

这个问题是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"

答案 1 :(得分:1)

问题与 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")