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)
// 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`.
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:
val functions = List(isEvenFunction) // works
val methods = List(isEvenMethod) // works
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.
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.
Contributors to this page:
Contents
- Introduction
- Scala Features
- Why Scala 3?
- A Taste of Scala
- Hello, World!
- The REPL
- Variables and Data Types
- Control Structures
- Domain Modeling
- Methods
- First-Class Functions
- Singleton Objects
- Collections
- Contextual Abstractions
- Toplevel Definitions
- Summary
- A First Look at Types
- Control Structures
- Domain Modeling
- Tools
- OOP Modeling
- FP Modeling
- Methods
- Method Features
- Main Methods in Scala 3
- Summary
- Functions
- Anonymous Functions
- Function Variables
- Eta Expansion
- Higher-Order Functions
- Write Your Own map Method
- Creating a Method That Returns a Function
- Summary
- Packaging and Imports
- Scala Collections
- Collections Types
- Collections Methods
- Summary
- Functional Programming
- What is Functional Programming?
- Immutable Values
- Pure Functions
- Functions Are Values
- Functional Error Handling
- Summary
- Types and the Type System
- Inferred Types
- Generics
- Intersection Types
- Union Types
- Algebraic Data Types
- Variance
- Opaque Types
- Structural Types
- Dependent Function Types
- Other Types
- Contextual Abstractions
- Extension Methods
- Context Parameters
- Context Bounds
- Given Imports
- Type Classes
- Multiversal Equality
- Implicit Conversions
- Summary
- Concurrency
- Scala Tools
- Building and Testing Scala Projects with sbt
- Worksheets
- Interacting with Java
- Scala for Java Developers
- Scala for JavaScript Developers
- Scala for Python Developers
- Where To Go Next