I would like to pass a closure to a method as an Option and I am doing what is shown below. I get a compile error as shown below. Is it possible to pass an optional closure parameter to a function?
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
Because closures can be used just like strings and integers, you can pass them into functions.
It doesn't make sense to add escaping annotations to optional closures because they aren't function types: they are basically an enum (Optional) containing a function, the same way you would store a closure in any type: it's implicitly escaping because it's owned by another type.
Said differently, a closure is a block of code that you can assign to a variable. You can then pass it around in your code, for instance to another function. The function then calls the closure and executes its code, as if the closure is an ordinary function.
The error message is pretty explicit: sampleMethod
expects an Option
, but you are passing a straight function value (not wrapped in Some
).
The simplest way to fix this is to wrap optMethod
into a Some
:
sampleMethod("hi", "bye", Some(optMethod))
But if you want to be able to simply do sampleMethod("hi", "bye", optMethod)
, you could add overloaded definitions of 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
As pointed out earlier, your method expects an Option
value containing the optionalMethod
. You must hence pass an Option
value to it:
// invoke with method
sampleMethod("hi", "bye", Some(optMethod))
// invoke without method
sampleMethod("hi", "bye", None)
If you want to avoid the Option
value (esp. avoid the None
), you can try the following:
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")
How about
sampleMethod("hi", "bye", Some(optMethod))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With