Scala - DSL:重载前缀函数模糊

时间:2012-09-11 08:48:07

标签: scala dsl overloading currying

在我的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:Boolean,onDisable:Boolean)(c:   组件)依赖于类Test的组件和方法(c:   组件)组件匹配预期类型?

但如果我将参数括在括号中:

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

错误消失了。显然,编译器在使用无括号的情况下失败了。这是预期还是我做错了什么?如果这是预期的,那么为什么呢?如何回收使用方法dependant作为前缀的能力,不带括号?

2 个答案:

答案 0 :(得分:2)

如果你提供一个对象,写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)))

答案 1 :(得分:2)

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

请参阅Scala - Prefix Unary Operators

另一种方法是使用后缀表示法(如Component("parameters") dependant中所述)。 如果您可以修改Componenet的实现,这只是意味着将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,则可以使用“pimp my library idiom”。 有关此习语的简短介绍,请参阅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
}