I'm trying to understand the crucial difference between these two approaches of referencing / defining Function Literal
(reference to anonymous function
):
By val
scala> val v2 = new Function[Int, Int] {
| def apply(a: Int): Int = a + 1
| }
v2: Int => Int = <function1>
And by def
scala> def f2 = new Function[Int, Int] {
| def apply(a: Int): Int = a + 1
| }
f2: Int => Int
It seems that it pretty much the same in terms of use. I either can pass v2
or f2
to the function that accepts (Int) => Int
as an argument. Passing arguments to its..
I guess or the case of v2 it creates an Function1
object that refers to the Function1
object.. like a proxy
?
Ok.. My question is: what is advantage and disadvantages of 1th and 2nd approach?
And of it is defined by def
, is it still Function Literal
?
First of all, neither of your examples are actually function literals—you're creating a Function
instance in the plain old sugar-free way, and in fact you could use this approach (new Function { ... }
) to create an instance of scala.Function
from Java code.
The following are both function literals, and are exactly equivalent to your definitions:
val v2 = (a: Int) => a + 1
def f2 = (a: Int) => a + 1
The only real difference here is that the val
will create a single instance once and for all, no matter how many times you use v2
(and even if you never use it), while the def
will create a new instance every time (or not at all, if you never use it). So you'll generally want to go with a val
.
There are cases, however, where you need to use def
. Consider the following:
def myIdentity[A] = (a: A) => a
There's no way we could write this as a val
, since Scala doesn't have polymorphic functions in this sense (for any instance of Function[A, B]
, A
and B
have to be concrete types). But we can define a polymorphic method that returns a function, and when we write e.g. myIndentity(1)
, the A
will be inferred to be Int
, and we'll create (and apply) a Function[Int, Int]
exactly as you'd expect.