我是Scala的新手,试图掌握DSL创作技巧。当 a)我直接实例化B类而 b)当我通过包装方法执行相同操作时,无法弄清楚为什么编译器在以下两种情况下表现不同值。
contains
答案 0 :(得分:1)
你的第一个例子:
createA aMethod new B { s: String => }
可能会编译,但它没有按照您的期望进行。您实际上是在构建一个B实例,其自身类型为String(有关更多信息,请参阅this和this)。然后,该语句的返回类型是一个Function,它将String的Function转换为Unit并返回Unit。更简单地说,您没有为函数aMethod提供参数p的值。
你在这三个例子中的问题只是一个语法问题。编译器真的很困惑,不知道你在哪里给它一个函数以及你在哪里扩展类。在这种情况下,我喜欢显式添加函数调用的句点和parens。现在,所有这三个都应该编译并执行您想要的操作:
createA.aMethod(new B) { s: String =>
}
createA.aMethod(createB){ s: String =>
}
val bb = new B
createA.aMethod(bb){ s: String =>
}
编辑: 通过直接调用适用于curried函数的替代方案,这可能是您最好的选择:
class A {
def aMethod(b: B)(p: String => Unit): Unit = {}
}
def main(args: Array[String]) {
createA aMethod new B apply { s: String =>
}
createA aMethod createB apply { s: String =>
}
val bb = new B
createA aMethod bb apply { s: String =>
}
}
如果你讨厌使用'apply',你也可以用你想要的任何名称构建一个对象:
class A {
def aMethod(b: B) = new {
def myCoolName(p: String => Unit): Unit = {}
}
}
def main(args: Array[String]) {
createA aMethod new B myCoolName { s: String =>
}
createA aMethod createB myCoolName { s: String =>
}
val bb = new B
createA aMethod bb myCoolName { s: String =>
}
}
另一种方法是使用方法而不是咖喱:
class A {
def aMethodNotCurried(b: B, p: String => Unit): Unit = {}
}
def mainNotCurried(args: Array[String]) {
createA aMethodNotCurried (new B, { s: String =>
})
createA aMethodNotCurried (createB, { s: String =>
})
val bb = new B
createA aMethodNotCurried (bb, { s: String =>
})
}