Scala 如何将可选闭包参数传递给函数?
我想将闭包作为一个选项传递给一个方法,我正在做如下所示的事情。我得到一个编译错误,如下所示。是否可以将可选的闭包参数传递给函数Scala 如何将可选闭包参数传递给函数?,scala,Scala,我想将闭包作为一个选项传递给一个方法,我正在做如下所示的事情。我得到一个编译错误,如下所示。是否可以将可选的闭包参数传递给函数 def sampleMethod(a: String, b: String, optionalMethod: Option[(String, Int) => Unit]) { // do some processing with a and b optionalMethod match { case Some(optionalMetho
def sampleMethod(a: String, b: String, optionalMethod: Option[(String, Int) => Unit]) {
// do some processing with a and b
optionalMethod match {
case Some(optionalMethod) => {
optionalMethod("a",3)
}
case _
log("no optional method passed")
}
}
// definition of optMethod in some other place
val optMethod = (c: String, d: Int) => {
// some processing with c, d and external values
}
// invoke
sampleMethod("hi", "bye", optMethod) => FAILS TO COMPILE
ERROR = type mismatch. expecting Option[(String, Int) => Unit] found (String, Int) => Unit
怎么样
sampleMethod("hi", "bye", Some(optMethod))
如前所述,您的方法需要一个
选项
值,该值包含optionalMethod
。因此,必须将选项
值传递给它:
// invoke with method
sampleMethod("hi", "bye", Some(optMethod))
// invoke without method
sampleMethod("hi", "bye", None)
如果要避免使用选项
值(特别是避免使用无
),可以尝试以下操作:
def sampleMethod(a: String, b: String, optionalMethod: (String, Int) => Unit = (_, _) => log("no optional method passed")) {
optionalMethod("a", 3)
}
// invoke with method
sampleMethod("hi", "bye", optMethod)
// invoke without method
sampleMethod("hi", "bye")
更清楚的是:
scala> def sampleMethod(a: String, b: String, optionalMethod: Option[(String, Int) => Unit]) {
| optionalMethod.map(f => f("a", 3))
| }
sampleMethod: (a: String, b: String, optionalMethod: Option[(String, Int) => Unit])Unit
scala> sampleMethod("A", "A", Some((c:String, d:Int) => println(s"Hello wolrd $c...$d")))
Hello wolrd a...3
您只需在可选函数周围添加“Some()”错误消息非常明确:
sampleMethod
需要一个选项,但您传递的是一个直接的函数值(不是封装在Some
)
解决此问题的最简单方法是将optMethod
包装成Some
:
sampleMethod("hi", "bye", Some(optMethod))
但是,如果您希望能够简单地执行sampleMethod(“hi”,“bye”,optMethod)
,您可以添加sampleMethod
的重载定义:
object Test {
def sampleMethod(a: String, b: String, optionalMethod: Option[(String, Int) => Unit]) {
// do some processing with a and b
optionalMethod match {
case Some(optionalMethod) => {
optionalMethod("a",3)
}
case _ => log("no optional method passed")
}
}
def sampleMethod(a: String, b: String) { sampleMethod(a, b, None) }
def sampleMethod(a: String, b: String, optionalMethod: (String, Int) => Unit) {
sampleMethod(a, b, Some(optionalMethod))
}
}
val optMethod = (c: String, d: Int) => {
// some processing with c, d and external values
}
// invoke
Test.sampleMethod("hi", "bye", optMethod) // Now Compiles fine
Test.sampleMethod("hi", "bye") // This too
sampleMethod(“hi”,“bye”,Some(optMethod))optionalMethod.map(f=>f(“a”,3))要更清晰一些,只是因为其他语言及其用户社区在术语方面不规范,我们在这里不做同样的事情。“Closure”是指在函数文本中使用自由变量(函数体中没有绑定的名称),并将这些引用“close”到词汇环境中。并非所有函数都涉及到词法环境。并非所有函数都是函数文本。例如,它们通常是通过“部分应用”另一个函数或一个方法创建的(由编译器自动透明地创建或显式创建)。我认为重载比对函数参数使用选项
要好得多。你的意思是只使用两个重载(一个带参数,一个不带参数)而不是我的答案中的3个重载?如果是这样的话,问题是在一般情况下,两种情况之间可能有足够多的共同行为,您希望将其分解为单个实现(如我的第一个重载,它完成了所有工作),并且有足够多的差异,仅仅为optionalMethod
设置一个默认值(如@fynn的答案)可能是不够的。这在很大程度上取决于实际需要。然后创建一个私有方法来完成这项工作,并使用选项[Function]
,然后由重载了函数和不重载函数的公共方法调用。这正是我所做的,只是实现是公共的而不是私有的。实际上,我认为最好将其公开,因为它的组成更好:如果在某一点上你得到一个选项[(String,Int)=>Unit]
值,并想将其传递给sampleMethod
,它可以立即完成,但如果使用选项的重载是私有的,我必须匹配选项并调用一个重载或另一个重载(加上复制参数列表的其余部分)。这对我来说不是胜利。