Published 2013-10-21.
Last modified 2015-09-20.
Time to read: 7 minutes.

Partially applied functions are used in many libraries. You can use them without realizing how they work. This lecture removes the mystery so you can write them. An anti-pattern for partial function usage is shown, followed by a working example of a pattern that uses partial functions to design layered software where each layer is independent of the layers below.
The sample code for this lecture is provided in the
courseNotes/
Scala worksheet.
Partially applied functions could also be called partially bound functions.
These lecture notes will refer to partially applied Function
s to emphasize that is what they are.
More precisely, partially applied functions are instances of FunctionN
,
where N
might vary between
1 and
22.
Terminology
Let’s agree upon some terminology before we go any further.
-
A parameter declares the name and type of a value that must be supplied by the caller to
a method or
FunctionN
that receives the value. -
An argument is the value of an expression passed to a method or
FunctionN
when it is called.
Here are examples of parameters and arguments:
/** @param param1 is a String parameter that must be supplied * @param param2 is an Int parameter that must be supplied */ def myMethod(param1: String, param2: Int) = ???
// Invoke myMethod with two arguments: "argument1" and 2 myMethod("argument1", 2)
Recall from the Functions are First Class lecture of the
Introduction to Scala
course that you can lift a method from an object into a FunctionN
instance by following the
method body with an underscore.
Lifting is also called eta expansion.
scala> val tooString = "Tootoo!".toString _ tooString: () => String = <function0>
scala> tooString() res1: String = Tootoo!
Partially applied Function
s are created when you supply some,
but not all arguments to a FunctionN
instance;
you can fill in the remaining arguments when you invoke the function at a later time.
As an analogy, let’s pretend a tandem bicycle is like a FunctionN
;
each seat can be considered as an FunctionN
parameter,
and adding riders to the bicycle is similar to binding arguments to the parameter list.
Seats are places for riders to sit, just like parameters are slots for providing arguments to methods.
Setting the Scene
We need two case classes to set the scene for this lecture’s example:
case class Rider(name: String, weight: Double, height: Double) { override def toString = s"""$name is $weight pounds and $height" tall""" }
case class Bike(rider1: Rider, rider2: Rider, rider3: Rider, color: String) { lazy val riders = List(rider1, rider2, rider3) lazy val names = riders.map(_.name) lazy val totalWeight: Double = riders.map(_.weight).sum lazy val cheer = s"Go $color team" + riders.map(_.name).mkString(": ", ", ", "!") }
Now we’ll create some Rider
instances:
scala> val chloe = new Rider("Chloe", 124, 62) chloe: Rider = Chloe is 124.0 pounds and 62.0" tall
scala> val louise = new Rider("Louise", 136, 68) louise: Rider = Louise is 136.0 pounds and 68.0" tall
scala> val beth = new Rider("Beth", 112, 59) beth: Rider = Beth is 112.0 pounds and 59.0" tall
Partially Applying the apply Method
Recall from the Case Classes lecture of the
Introduction to Scala
course that the automatically generated companion objects of case classes have apply
factory methods.
We are now ready to create a partially applied FunctionN
from a companion object’s apply
method.
We can do that two ways:
-
Eta Expansion.
If we partially apply the
apply
method then we get a function that, given case class arguments as parameters, creates an instance of the class.Scala REPLscala> val newRider = Rider.apply _ newRider: (String, Double, Double) => Rider = <function3>
scala> newRider("Monique", 140, 69) res0: Rider = Monique is 140.0 pounds and 69.0" tall -
Placeholder syntax.
Provide an underscore and the expected type for any method parameter for which you do not wish to bind a value:
Scala REPL
scala> val team1 = Bike(chloe, louise, beth, _: String) team1: String => Bike = <function1>
Remember that in Scala, underscores perform many purposes. A common purpose is to act as a placeholder, and that is what it is used for in the above. The underscore tells the compiler to lift theBike.apply
method to a newFunction1
instance that just has the first 3 arguments applied (we say the three first three parameters of theFunction1
instance are bound to the argumentschloe
,louise
andbeth
). The fourth parameter will be supplied later (it is unbound). Let’s do that now.
Scala REPLscala> val bike1 = team1("red") bike1: Bike = Bike(Chloe is 124.0 pounds and 62.0" tall,Louise is 136.0 pounds and 68.0" tall,Beth is 112.0 pounds and 59.0" tall,red)
scala> bike1.cheer res2: String = Go red team: Chloe, Louise, Beth!If a partially applied function has N unbound parameters then it is represented by a FunctionNIf we had supplied four arguments toBike.apply
, a newBike
would have been returned. Instead, the type forteam1
isString => Bike
, or in other words it is aFunction1
that accepts aString
(for theColor
parameter) and returns aBike
; thisFunction1
is actually aBike
factory. The underscore provided in place of the last parameter caused a partially appliedFunction1
to be returned instead of aBike
instance.
Underscores for placeholder syntax can be used in place of any argument, and they can appear in any position. Here is an example.
scala> val oneRider = Bike(_: Rider, _: Rider, chloe, _: String) oneRider: (Rider, Rider, String) => Bike = <function3>
oneRider
has type (Rider, Rider, String) => Bike
, which means that it is a
Function3
instance that accepts three parameters (Rider
, Rider
, String
) and returns a Bike
.
Yes, it is also a factory method.
We can bind two more arguments to oneRider
, and create another partially applied function, like this.
scala> val team2 = oneRider(louise, beth, _: String) team2: String => Bike = <function1>
You can see that team2
was created by calling oneRider
and supplying two of the necessary arguments to create a Bike
.
Because an underscore was provided in place of the last argument, team2
is also a partially applied
Function1
with type String => Bike
.
This means we can now produce a Bike
by binding a String
to team2
for the color
argument.
scala> val bike2 = team2("blue") bike2: Bike = Bike(Louise is 136.0 pounds and 68.0" tall,Beth is 112.0 pounds and 59.0" tall,Chloe is 124.0 pounds and 62.0" tall,blue)
scala> s"""bike2 riders are: ${bike2.names.mkString(", ")}""" res3: String = bike2 riders are: Louise, Beth, Chloe

Curried Functions
A method with multiple parameter lists is lifted into a chain of FunctionN
s.
As you know, Function1
instances accept only one parameter.
Chains of Function1
instances are called curried functions.
You can curry a regular method or FunctionN
by using Scala’s built-in curried
method.
Since it makes no sense to curry a Function1
, let’s curry oneRider
, which is a Function3
.
scala> oneRider.curried res5: Rider => (Rider => (String => Bike)) = <function1>
The returned type is interesting: Rider => (Rider => (String => Bike))
.
Let’s pull that apart.
I’ve color-coded the chained Function1
s so you can recognize them more easily.
What we have is a Function1
that transforms a Rider
into something which we can represent with X
.
Rider => X
...where X
is also a Function1
that transforms a Rider
into something which we can represent as Y
.
Rider => Y
Pulling Y
apart, we discover yet another Function1
that transforms a String
into a Bike
.
String => Bike
Now you know how to recognize a curried method signature – a chain of Function1
s followed by a final type.
The Function1
chain is written as nested parentheses.
We can use our knowledge of how method lifting works to curry the automatically generated Bike.apply
method; recall that it accepts four parameters.
scala> val curriedBike = (Bike.apply _).curried curriedBike: Rider => (Rider => (Rider => (String => Bike))) = <function1>
As you see, we get a similar return type as before: a chain of Function1
s.
The companion object of a case class has a convenience method, also called curried
,
that also curries the companion object’s apply
method.
scala> val curriedBike2 = Bike.curried curriedBike2: Rider => (Rider => (Rider => (String => Bike))) = <function1>
Regardless of how you curried apply
you can invoke it by providing all its parameters like this:
scala> val bike3 = curriedBike(chloe)(louise)(beth)("yellow") bike3: Bike = Bike(Chloe is 124.0 pounds and 62.0" tall,Louise is 136.0 pounds and 68.0" tall,Beth is 112.0 pounds and 59.0" tall,yellow)
Creating Partially Applied Functions From Curried Functions
Notice that each of the arguments to curriedBike
were provided as separate parameter lists.
This is helpful because curried functions can be turned into partially applied Function
s two ways:
using the placeholder shorthand sytax that we saw a moment ago, and by using a second shorthand that is convenient for many circumstances.
Method 1: Placeholder Shorthand
Here are some examples of creating partially applied functions using placeholder shorthand:
scala> val oneRiderB1 = Bike.curried(chloe)(_: Rider)(_: Rider)(_: String) oneRiderB1: (Rider, Rider, String) => Bike = <function3>
scala> val oneRiderB2 = curriedBike(_: Rider)(louise)(_: Rider)(_: String) oneRiderB2: (Rider, Rider, String) => Bike = <function3>
scala> scala> val oneRiderB3 = Bike.curried(_: Rider)(_: Rider)(beth)(_: String) oneRiderB3: (Rider, Rider, String) => Bike = <function3>
Method 2: Eta Expansion Without the Trailing Underscore
The second type of shorthand is just like eta expansion, but without the trailing underscore.
This type of shorthand is only possible for curried functions.
For examples, if only the first parameter is bound to an argument, the remaining parameters can simply be ignored,
and a partially applied FunctionN
will be created.
scala> val oneRiderC = Bike.curried(chloe) oneRiderC: Rider => (Rider => (String => Bike)) = <function1>
We can bind the second Rider
parameter using the same syntax:
scala> val twoRiders = oneRiderC(louise) oneRiderC: (Rider => (String => Bike) = <function1>)
We can bind the third Rider
parameter using the same syntax.
scala> val team4a = twoRiders(beth) team4a: String => Bike = <function1>
Finally, invoking team4a
and supplying an argument for the color
parameter yields a Bike
.
scala> val bike4 = team4a("green") bike4: Bike = Bike(Chloe is 124.0 pounds and 62.0" tall,Louise is 136.0 pounds and 68.0" tall,Beth is 112.0 pounds and 59.0" tall,green)
scala> val weight4 = s"Team ${bike4.color} weighs ${bike4.totalWeight} pounds" weight4: String = Team green weighs 372.0 pounds
Uncurrying
We can also uncurry a function, which creats an equivalent function with one parameter list.
scala> val uncurriedBike = Function.uncurried(curriedBike) uncurriedBike: (Rider, Rider, Rider, String) => Bike = <function4>
scala> val bikex = uncurriedBike(chloe, louise, beth, "Brown") bikex: Bike = Bike(Chloe is 124.0 pounds and 62.0" tall,Louise is 136.0 pounds and 68.0" tall,Beth is 112.0 pounds and 59.0" tall,Brown)
Note that currying and uncurrying only works on FunctionN
s, not methods.
scala> Bike.apply.curried <console>:9: error: missing arguments for method repeat2 in object R2; follow this method with `_’ if you want to treat it as a partially applied function R2.repeat2.curried

AntiPatterns: Eager Evaluation and Closing Over External State
We defined an unless
construct in the More Fun With Functions
lecture of the Introduction to Scala course.
def unless(cond: Boolean)(body: => Unit): Unit = if (!cond) body
And we were able to call it like this:
scala> var x = 1 x: Int = 1
scala> unless(x == 0) { println(s"I can divide by x because x is not zero: ${3 / x}") } I can divide by x because x is not zero: 3
scala> x = 0 x: Int = 0
scala> unless(x == 0) { println(s"I can divide by x because x is not zero: ${3 / x}") }
The argument bound to the body
parameter of the unless
method above is an example of a closure,
which was discussed in the Closures lecture of the
Introduction to Scala course.
That code works fine when used as shown.
However, you should be cautious about making partially applied functions from arbitrary methods and functions without
considering eager evaluation issues and possible race conditions when closing over mutable state.
Here is an example of both types of errors in action.
scala> x = 1 x: Int = 1
scala> val isNonZero = unless(x==0) _ isNonZero: (=> Unit) => Unit = <function1>
scala> isNonZero { println(s"x==$x") } x==1
scala> var x = 0 x: Int = 0
scala> isNonZero { println(s"x==$x") } // we expect no result to be printed, right? x==0
The problem that manifested is that the unless
method eagerly evaluates the cond
parameter,
which means that the value of x
when the partially applied function was created is used,
and the value of the parameter is never recomputed.
The problem goes away if we lazily evaluate that parameter.
scala> def unless(cond: => Boolean)(body: => Unit): Unit = if (!cond) body unless: (cond: => Boolean)(body: => Unit)Unit
scala> val isNonZero = unless(x==0) _ isNonZero: (=> Unit) => Unit = <function1>
scala> isNonZero { println(s"x==$x") } // no result is printed, which is correct %}
Even with this correction, the closure passed to the partially applied function and bound to the body
parameter is sensitive to race conditions when the value of x
changes,
which we will discuss in the MultiThreading lecture.
Partially applied functions should not reference mutable state in outer scopes.
Instead, to be safe, partially applied functions should receive parameters for all external mutable state.

Pattern: Designing Layered Software
Let’s write a small program that simulates a graffiti artist.
The SprayPaint
class will be designed such that the base functionality is contained within the class, but higher-level functionality is defined elsewhere.
We will use partially applied functions to drop in sequences of operations using SprayPaint
.
This allows us to define another higher-level class that uses the SprayPaint
class to make paintings or write messages.
Let’s start the design of the SprayPaint
class by just defining the properties.
/** @param color pigment color of this spray can of paint * @param capacityRemaining milliliters of paint remaining in this can * @param gramsPerMeter amount of paint required to spray a line one meter long * @param maybeWhenLastShaken Some(Date) of when the can was last shaken, defaults to None which means never shaken */ case class SprayPaint( color: String, var capacityRemaining: Double, gramsPerMeter: Double, secondsBetweenShakes: Long=15, var maybeWhenLastShaken: Option[Date]=None ) { // more methods will go here }
Now let’s add some low-level methods to this class.
@inline def distanceRemaining: Double = capacityRemaining / gramsPerMeter
@inline def doesNotNeedShaking: Boolean = maybeWhenLastShaken.exists(new Date().getTime - _.getTime <= secondsBetweenShakes * 1000)
@inline def isEmpty: Boolean = capacityRemaining==0
@inline def needsShaking = !doesNotNeedShaking
@inline def nonEmpty: Boolean = !isEmpty
@inline def shake(): Unit = maybeWhenLastShaken = { println("Can is ready to spray") Some(new Date) }
The spray
method uses many of the other methods.
@inline def spray(distance: Double, degrees: Double) = { if (needsShaking) println("Cannot spray, need to shake the paint can") else { val remaining = distanceRemaining if (remaining<distance) println (f"Spraying $distance%.1f meters @ $degrees%.1f degrees.") else println (f"Spraying $remaining%.1f meters @ $degrees%.1f degrees.") capacityRemaining = math.max(0, capacityRemaining-gramsPerMeter*distance) if (isEmpty) println("Can is empty.") } }
Here is one more method for the SprayPaint
class, rather important for this code example.
It accepts three parameter lists: the first is a
java.awt.Point
which acts as a reference point for the operation to be performed.
The second parameter list is a scale factor; larger values will affect the amount of surface area for the operation.
The third parameter list is a Function3[Point, Double, SprayPaint, Unit]
that defines the operation to be carried out with the block of code.
This is an examples of a pattern common to partial functions: if one of the parameters of a curried function is an operation,
it needs to be a FunctionN
that accepts at all of the other parameters plus an instance of the enclosing class,
so it can do something with them.
@inline def doIfNonEmpty(origin: Point) (scale: Double) (action: (Point, Double, SprayPaint) => Unit): Unit = if (nonEmpty) action(origin, scale, this) else println("Sorry, paint can is empty")
The PatternArtist
class knows how to draw things with spray paint.
Notice how drawTriangle
is a partial function defined using placeholder syntax that accepts an origin
(a Point
) and a scale factor (a Double
), and draws a pattern using the SprayPaint
methods.
case class PatternArtist(sprayPaint: SprayPaint) { val drawTriangle = sprayPaint.doIfNonEmpty(_: Point)(_: Double) { (origin, scale, self) => self.shake() self.moveTo(new Point((origin.getX*scale).toInt, (origin.getY*scale).toInt)) self.spray(scale, 45) self.spray(scale, -45) self.spray(scale, 180) if (self.nonEmpty) println(f"Spray paint can has ${self.capacityRemaining}%.1f milliliters remaining and can spray ${self.distanceRemaining}%.1f meters more.") } }
This allows us to write high-level code that is independent of the SprayPaint
implementation,
and also independent of the PatternArtist
implementation.
// draw concentric green triangles val greenArtist = PatternArtist(SprayPaint("green", 355, 6.3)) val origin = new Point(0, 0) greenArtist.drawTriangle(origin, 1.0) greenArtist.drawTriangle(origin, 2.0) greenArtist.drawTriangle(origin, 3.0)

Now you know how to use partial functions to design layered software where each layer is independent of the layers below.
You can run this code example by typing:
$ sbt "runMain Banksy" Can is ready to spray Moving nozzle to 0.0, 0.0 Spraying 56.3 meters @ 45.0 degrees. Spraying 55.3 meters @ -45.0 degrees. Spraying 54.3 meters @ 180.0 degrees. Spray paint can has 336.1 milliliters remaining and can spray 53.3 meters more. Can is ready to spray Moving nozzle to 0.0, 0.0 Spraying 53.3 meters @ 45.0 degrees. Spraying 51.3 meters @ -45.0 degrees. Spraying 49.3 meters @ 180.0 degrees. Spray paint can has 298.3 milliliters remaining and can spray 47.3 meters more. Can is ready to spray Moving nozzle to 0.0, 0.0 Spraying 47.3 meters @ 45.0 degrees. Spraying 44.3 meters @ -45.0 degrees. Spraying 41.3 meters @ 180.0 degrees. Spray paint can has 241.6 milliliters remaining and can spray 38.3 meters more.
© Copyright 1994-2024 Michael Slinn. All rights reserved.
If you would like to request to use this copyright-protected work in any manner,
please send an email.
This website was made using Jekyll and Mike Slinn’s Jekyll Plugins.