2013-02-08 57 views
6

我想将一个闭包传递给一个方法作为一个选项,我正在做如下所示。我得到一个编译错误,如下所示。是否可以将一个可选的闭包参数传​​递给一个函数?如何将可选的闭包参数传​​递给函数?

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 
+0

sampleMethod(“hi”,“bye”,Some(optMethod)) – twillouer 2013-02-08 15:03:49

+0

optionalMethod.map(f => f(“a”,3))更清晰 – twillouer 2013-02-08 15:04:36

+1

只是因为其他语言及其用户群体sl with不乐termino逻辑,我们不要在这里做同样的事情。 “关闭”是指在函数文字中使用自由变量(在该函数的主体中没有绑定的名称),并将这些引用“关闭”到词法环境中。并非所有功能都涉及到关闭词汇环境。并非所有函数都是函数文字。例如,它们经常通过另一个功能或方法的“部分应用”来创建(由编译器自动或透明地编译或显式地创建)。 – 2013-02-08 15:46:47

回答

3

如何

sampleMethod("hi", "bye", Some(optMethod)) 
6

正如前面所指出的那样,你的方法需要包含optionalMethodOption值。如果你想避免Option

// invoke with method 
sampleMethod("hi", "bye", Some(optMethod)) 
// invoke without method 
sampleMethod("hi", "bye", None) 

,你可以尝试以下方法:必须将Option值,因此传递给它(ESP避免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") 
0

更加清晰:

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 

您必须只需添加 “有些()” 在你optinal功能

7

错误消息非常明确:sampleMethod需要Option,但是您传递的是直函数值(未包含在Some中)。

解决这个问题的最简单的方法是包装optMethodSome

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 
+0

我认为重载比使用'Option'作为函数参数要好得多。 – 2013-02-08 15:34:20

+0

你的意思是只使用2个重载(一个有参数,一个没有),而不是3个重载,就像我的答案一样?如果是这样的话,那么在一般情况下,两种情况之间可能存在足够的共同行为,您想将其分解为单个实现(就像在我的第一个重载中完成所有工作一样),并且存在足够的差异'optionalMethod'的默认值(如@ fynn的答案)可能不够。这很大程度上取决于实际需要。 – 2013-02-08 15:59:40

+2

然后创建一个私有方法来完成这项工作,并采用'Option [Function]',然后通过公共方法调用带有或不带'Function'的重载方法。 – 2013-02-08 16:19:47

相关问题