9.6 Partial Application
In addition to lambda expressions, currying, and λ-conversion, partial application is yet another mechanism used to create function values. In Scala, it takes the form of an underscore used in place of a part of an expression. This produces a function that, when applied, replaces the underscore with its argument in the given expression. For instance, the following code searches for a temperature greater than 90 (in Fahrenheit) in a list of Celsius temperatures:
Scala
celsiusTemps.find(temp => temp * 1.8 + 32 > 90)
Instead of a lambda expression, you can build the desired function argument by replacing temp with an underscore in the expression temp * 1.8 + 32 > 90:
Scala
celsiusTemps.find(_ * 1.8 + 32 > 90)
The expression _ * 1.8 + 32 > 90 represents a Boolean function that maps temp to temp * 1.8 + 32 > 90, just like the function defined by the lambda expression temp => temp * 1.8 + 32 > 90. Searches written earlier using lambda expressions can use partial application instead:
Scala
temps.find(_ > 90) projects.find(_.id == 12345L)
Partial application is generalized to multi-argument functions by using several underscores in the same expression. For instance, _ * 1.8 + 32 > _ is a two-argument function that compares a Celsius temperature to a Fahrenheit bound, and _.id == _ is a function that takes a project and an identity and checks whether the project has the given identity.5
Partial application can easily be abused. Code is often easier to read with lambda expressions that name (and sometimes type) their arguments. Compared to the shorter _.id == 12345L, the longer expression project => project.id == 12345L makes it clearer that projects are being searched, and (project, id) => project.id == id is a lot easier to read than _.id == _.