In Scala, can you make an anonymous function have

2020-02-05 05:15发布

问题:

This works:
scala> def test(name: String = "joe"): Boolean = true
test: (name: String)Boolean

I expected this to work in the same way:
scala> val test: String => Boolean = { (name: String = "joe") => true } <console>:1: error: ')' expected but '=' found.

回答1:

The boring, correct answer is no, you can't, but actually you kind of can, with the experimental single abstract method (SAM) synthesis in 2.11.

First you need to define your own SAM type with the default value for the apply method's parameter:

trait Func {
  def apply(name: String = "joe"): Boolean
}

Now you can use the function literal notation to define a Func (note that you'll need to have started the REPL with -Xexperimental for this step to work):

val f: Func = { (name: String) => name == "joe" }

Or just:

val f: Func = _ == "joe"

And then the usual stuff:

scala> f("joe")
res0: Boolean = true

scala> f("eoj")
res1: Boolean = false

And the punchline:

scala> f()
res2: Boolean = true

It's not exactly the syntax you're asking for, and there are no promises that this will ever leave experimental status, and even if it does, default arguments may not be supported—but I still think it's pretty neat that it works now.



回答2:

To expand on "The boring, correct answer is no" in Travis Brown's answer:

Functions (i.e. objects of FunctionN[...] type) can't have default arguments in Scala, only methods can. Since anonymous function expressions produce functions (and not methods), they can't have default arguments.



回答3:

This is bit dirty solution I think, using currying

def testDef(nameDef: String)(name2: String): Boolean = { val name3 = if ( name2 != "") name2 else nameDef //use name3 for your logic true } //> testDef: (name: String)(name2: String)Boolean

Curry the testDef method to hold default value as shown below.

var test = test("joe")_ //> test : String => Boolean=function1

test("fun") //"fun" will be used as name3
test("") // "joe" will be used as name3