When you look at the Scaladoc for the
map method on Scala collections classes, you see that it’s defined to accept a function:
def map[B](f: (A) => B): List[B] -----------
Indeed, the Scaladoc clearly states, “
f is the function to apply to each element.”
But despite that, somehow you can pass a method into
map, and it still works:
def times10(i: Int) = i * 10 // a method List(1, 2, 3).map(times10) // List(10,20,30)
Have you ever wondered how this works—how you can pass a method into
map, which expects a function?
The technology behind this is known as Eta Expansion. It converts an expression of method type to an equivalent expression of function type, and it does so seamlessly and quietly.
The differences between methods and functions
Historically, methods have been a part of the definition of a class, although in Scala 3 you can now have methods outside of classes, such as Toplevel definitions and extension methods.
Unlike methods, functions are complete objects themselves, making them first-class entities.
Their syntax is also different. This example shows how to define a method and a function that perform the same task, determining if the given integer is even:
def isEvenMethod(i: Int) = i % 2 == 0 // a method val isEvenFunction = (i: Int) => i % 2 == 0 // a function
The function truly is an object, so you can use it just like any other variable, such as putting it in a list:
val functions = List(isEvenFunction)
Conversely, a method technically isn’t an object, so in Scala 2 you couldn’t put a method in a
List, at least not directly, as shown in this example:
// this example shows the Scala 2 error message val methods = List(isEvenMethod) ^ error: missing argument list for method isEvenMethod Unapplied methods are only converted to functions when a function type is expected. You can make this conversion explicit by writing `isEvenMethod _` or `isEvenMethod(_)` instead of `isEvenMethod`.
As shown in that error message, there is a manual way to convert a method into a function in Scala 2, but the important part for Scala 3 is that the Eta Expansion technology is improved, so now when you attempt to use a method as a variable, it just works—you don’t have to handle the manual conversion yourself:
val functions = List(isEvenFunction) // works val methods = List(isEvenMethod) // works
For the purpose of this introductory book, the important things to know are:
- Eta Expansion is the Scala technology that lets you use methods just like functions
- The technology has been improved in Scala 3 to be almost completely seamless
For more details on how this works, see the Eta Expansion page in the Reference documentation.