1

在我的 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")

因为它说

对重载定义的模棱两可的引用,依赖于类 Test 类型(onEnable:Boolean,onDisable:Boolean)(c:Component)组件和依赖于类 Test 类型(c:Component)Component 的方法与预期类型匹配?

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

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

错误消失了。显然,编译器无法消除无括号的情况。这是预期的还是我做错了什么?如果这是预期的,那么为什么?我怎样才能恢复使用该方法dependant作为前缀而不带括号的能力?

4

2 回答 2

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)))
于 2012-09-11T09:17:09.530 回答
2

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

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

另一种方法是使用后缀表示法(如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
}
于 2012-09-11T09:47:51.970 回答