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
,它可以立即完成,但如果使用
选项的重载是私有的,我必须匹配选项并调用一个重载或另一个重载(加上复制参数列表的其余部分)。这对我来说不是胜利。