【问题标题】:Scala DSL: How to add words that do "nothing"?Scala DSL:如何添加“无”的词?
【发布时间】:2016-04-23 17:17:18
【问题描述】:

我尝试在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") 可以工作,但 imo DSL 的句号和括号太多了)。

谢谢

【问题讨论】:

    标签: scala dsl implicit


    【解决方案1】:

    问题在于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"
    

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        猜你喜欢
        • 2011-04-10
        • 1970-01-01
        • 2019-03-10
        • 1970-01-01
        • 2010-10-31
        • 2018-03-07
        • 1970-01-01
        • 1970-01-01
        • 2019-03-08
        相关资源
        最近更新 更多