Scala-DSL:重载前缀函数歧义



在我的DSL中,我想要这个功能:

class Test {
  val compA = dependant(true, true)(Component("parameters"))
  //and this shortcut:
  val compB = dependant Component("parameters")
}

其中:

def dependant(onEnable: Boolean, onDisable: Boolean)(c: Component): Component = {
   //...
}
def dependant(c: Component): Component = dependant(false, true)(c)

一切都很好,但是,我不能使用以下语法:

val compB = dependant Component("parameters")

因为上面写着

对重载定义的引用不明确,两者都依赖于中的方法class类型的测试(onEnable:布尔,onDisable:布尔)(c:组件)依赖于组件和方法的类内测试类型(c:组件)组件是否符合预期类型?

但如果我把参数放在括号里:

val compB = dependant(Component("parameters"))

错误消失了。显然,编译器在取消加括号的情况下失败了。这是意料之中的事,还是我做错了什么?如果这是意料之中的事,那么为什么?如何恢复使用方法dependant作为前缀而不使用括号的能力?

dependant Component("parameters")中,您正试图使用前缀表示法来调用dependant。Scala对前缀表示法的支持是有限的。

请参阅Scala-前缀一元运算符。

另一种选择是使用后缀表示法(如Component("parameters") dependant)。如果您可以修改Componentet的实现,这只意味着将dependant方法添加到Component:

class Component(name: String) {
  def dependant: Component = //...
  def dependant(onEnable: Boolean, onDisable: Boolean): Component = {
    //...
  }    
}
class Test {
  val compA = Component("parameters") dependant(true, true)
  val compB = Component("parameters") dependant
}

如果你不能修改Component,你可以使用"拉皮条我的图书馆习语"。看见http://www.decodified.com/scala/2010/12/02/the-quickpimp-pattern.html关于这个习惯用法的简短介绍(以及下面关于使用匿名类的警告):

case class Component(name: String)
implicit def toPostifxDependentOps( c: Component ) = new {
  def dependant: Component = dependant(false, true)
  def dependant(onEnable: Boolean, onDisable: Boolean): Component = {
    //...
  }
}
class Test {
  val compA = Component("parameters") dependant(true, true)
  val compB = Component("parameters") dependant
}

如果提供对象,则编写myObject functionName param而不是myObject.functionName(param)可以正常工作。如果不这样做,编译器将丢失。例如:

scala> println("Hello")
Hello
scala> println "Hello"
<console>:1: error: ';' expected but string literal found.
       println "Hello"
           ^

一个可能的解决方法:创建一个对象来包装你的方法:

scala> case class Component(name: String, components: Option[Component] = None)
defined class Component
scala> object depends {def on(c: Component) = Component("dependant", Some(c))}
defined module depends
scala> depends on Component("foo")
res3: Component = Component(dependant,Some(Component(foo,None)))

最新更新