Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between these two ways to declare functions?

Tags:

scala

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.

like image 866
Dominykas Mostauskis Avatar asked Dec 25 '22 08:12

Dominykas Mostauskis


1 Answers

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.

like image 82
Nikita Volkov Avatar answered Apr 26 '23 22:04

Nikita Volkov