Follow two similar functions, a
and b
, declared differently:
scala> val a = { x:Int => x+x }
a: Int => Int = <function1>
scala> def b(x:Int) = x+x
b: (x: Int)Int
The only difference I can find between the two is that only with the def
function I can specify the parameter's name as I pass it (e.g. b(x=1)
). How are these functions different in other regards? Which should be used when?
Edit:
I also was not able to use the @tailrec
annotation with the val
method.
The principal difference is in how Scala translates those definitions. In Scala a lambda (an anonymous function, a function value, a function literal) and a method are different things. The first definition of yours is a sugar for an instance of a Function1
class, which is one of the classes used for lambdas, the second is just a method of the surrounding object, which compiles to a standard Java method.
The practical difference between the two is that Scala cannot just let you refer to a method as a value, which renders it a second class citizen. This results in redundant indirections when dealing with higher order functions. E.g., the following:
1.to(4).map(b)
desugars into a wrapper lambda:
1.to(4).map((x: Int) => b(x))
which is itself a sugar for:
1.to(4).map(
new Function1[Int, Int] {
def apply(x: Int): Int = b(x)
}
)
Feels like quite a redundancy, right? That is why if your intention with the function is for it to be used as a first class citizen (i.e., being passed around as value) it is more reasonable to declare it as a lambda from the beginning.
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