title | type | description | num | previous-page | next-page |
---|---|---|---|---|---|
Partial Functions |
section |
This page shows how to use partial functions in Scala. |
31 |
fun-function-variables |
fun-eta-expansion |
A partial function is a function that may not be defined for all values of its argument type. In Scala, partial functions
are unary functions implementing the PartialFunction[A, B]
trait, where A
is the argument type and B
the result type.
To define a partial function, use a case
identical to those used in match
expressions:
{% tabs fun-partial-1 %} {% tab 'Scala 2 and 3' %}
val doubledOdds: PartialFunction[Int, Int] = {
case i if i % 2 == 1 => i * 2
}
{% endtab %} {% endtabs %}
To check if a partial function is defined for an argument, use the isDefinedAt
method:
{% tabs fun-partial-2 %} {% tab 'Scala 2 and 3' %}
doubledOdds.isDefinedAt(3) // true
doubledOdds.isDefinedAt(4) // false
{% endtab %} {% endtabs %}
Trying to apply a partial function to an argument not belonging to its domain results in MatchError
:
{% tabs fun-partial-3 %} {% tab 'Scala 2 and 3' %}
doubledOdds(4) // Exception in thread "main" scala.MatchError: 4
{% endtab %} {% endtabs %}
A partial function can be passed as an argument to a method:
{% tabs fun-partial-4 %} {% tab 'Scala 2 and 3' %}
val res = List(1, 2, 3).collect({ case i if i % 2 == 1 => i * 2 }) // List(2, 6)
{% endtab %} {% endtabs %}
You can define a default value for arguments not in domain with applyOrElse
:
{% tabs fun-partial-5 %} {% tab 'Scala 2 and 3' %}
doubledOdds.applyOrElse(4, _ + 1) // 5
{% endtab %} {% endtabs %}
Two partial function can be composed with orElse
, the second function will be applied for arguments where the first
one is not defined:
{% tabs fun-partial-6 %} {% tab 'Scala 2 and 3' %}
val incrementedEvens: PartialFunction[Int, Int] = {
case i if i % 2 == 0 => i + 1
}
val res2 = List(1, 2, 3).collect(doubledOdds.orElse(incrementedEvens)) // List(2, 3, 6)
{% endtab %} {% endtabs %}