it may return
false
). Secondly, a function must not have side effects. That is, invoking
the function must not alter the state of the program. In our discussion of functions,
we haven’t seen functions with side effects (we are not considering console output to
be a side effect). Let’s consider a simple example:
const
colors
=
[
'red'
,
'orange'
,
'yellow'
,
'green'
,
'blue'
,
'indigo'
,
'violet'
];
let
colorIndex
=
-
1
;
function
getNextRainbowColor
() {
if
(
++
colorIndex
>=
colors
.
length
)
colorIndex
=
0
;
return
colors
[
colorIndex
];
}
The function
getNextRainbowColor
will return a different color each time, cycling
through the colors of the rainbow. This function is breaking both of the rules of a
pure function: it has a different return value each time for the same input (it has no
arguments, so its input is nothing), and it is causing a side effect (the variable
color
Index
changes). The variable
colorIndex
is not part of the function; invoking
getNex
tRainbowColor
modifies it, which is a side effect.
Going back to our leap year problem for a moment, how can we take our leap year
function and turn it into a pure function? Easy:
function
isLeapYear
(
year
) {
if
(
year
%
4
!==
0
)
return
false
;
else
if
(
year
%
100
!=
0
)
return
true
;
else
if
(
year
%
400
!=
0
)
return
false
;
else
return
true
;
}
This new function will always return the same output given the same input, and it
causes no side effects, making this a pure function.
Our
getNextRainbowColor
function is a little bit trickier. We can eliminate the side
effect by putting the external variables in a closure:
const
getNextRainbowColor
=
(
function
() {
const
colors
=
[
'red'
,
'orange'
,
'yellow'
,
'green'
,
'blue'
,
'indigo'
,
'violet'
];
let
colorIndex
=
-
1
;
return
function
() {
if
(
++
colorIndex
>=
colors
.
length
)
colorIndex
=
0
;
return
colors
[
colorIndex
];
};
})();
We now have a function that has no side effects, but it still isn’t a pure function
because it doesn’t always return the same result for the same input. To fix this prob‐
lem, we have to carefully consider how we use this function. Chances are, we’re call‐
186 | Chapter 13: Functions and the Power of Abstract Thinking