Skip to content

Commit 22ef474

Browse files
authored
clarify purity in the context of closures
1 parent 618dcee commit 22ef474

File tree

1 file changed

+18
-2
lines changed

1 file changed

+18
-2
lines changed

_overviews/scala3-book/fp-pure-functions.md

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Another feature that Scala offers to help you write functional code is the abili
1313
A _pure function_ can be defined like this:
1414

1515
- A function `f` is pure if, given the same input `x`, it always returns the same output `f(x)`
16-
- The function’s output depends _only_ on its input variables and its implementation
16+
- The function’s output depends _only_ on its input variables and its implementation (and in case of a closure, any immutable data that it captures)
1717
- It only computes the output and does not modify the world around it
1818

1919
This implies:
@@ -57,7 +57,7 @@ Conversely, the following functions are _impure_ because they violate the defini
5757

5858
Impure functions often do one or more of these things:
5959

60-
- Read from hidden state, i.e., they access variables and data not explicitly passed into the function as input parameters
60+
- Read from hidden mutable state, i.e., they access non-constant variables and data not explicitly passed into the function as input parameters.
6161
- Write to hidden state
6262
- Mutate the parameters they’re given, or mutate hidden variables, such as fields in their containing class
6363
- Perform some sort of I/O with the outside world
@@ -98,6 +98,22 @@ def double(i: Int): Int = i * 2
9898

9999
{% endtabs %}
100100

101+
The next example is bit more tricky. Here, i is not passed as a parameter, but instead referenced directly from the function body.
102+
This works in Scala because functions act as closure - they can capture the state around them. As long as that state is *immutable*, the function is still considered pure.
103+
In this case, the function always returns `6` and each call could be safely replaced with its result.
104+
This concept of closures and "fixing values" is an important tool in functional programming that you will encounter often as you go forward.
105+
106+
{% tabs fp-pure-function-closure %}
107+
108+
{% tab 'Scala 2 and 3' %}
109+
```scala
110+
val i = 3
111+
def double(i: Int): Int = i * 2
112+
```
113+
{% endtab %}
114+
115+
{% endtabs %}
116+
101117
If you’re comfortable with recursion, here’s a pure function that calculates the sum of a list of integers:
102118

103119
{% tabs fp-pure-recursive-function class=tabs-scala-version %}

0 commit comments

Comments
 (0)