While the use of immutable values eliminates many classes of errors when working with data in our programs, there are many other sorts of errors that are rooted in how we write the functions that work with those values. Most of these errors are due to side effects, changes that functions make to their environment in addition to their response of a return value.
Thinking back to our diagram in Figure 2-1, side effects are any interaction that a function has with the outside world in either direction. Any function that works with random numbers is a perfect example of a side-effecting function, as it:
Depends upon the state of the random number generator being used
Necessarily modifies the state of that random number generator, so the next caller of the function will end up working with a different series of random numbers than it otherwise would have
By definition, performing I/O of any kind or the modification of any shared mutable object are side effects.
Random numbers seem a bit prosaic, so perhaps these not-really-hypothetical functions are a bit more illustrative:
(defn perform-bank-transfer! [from-account to-account amount] ...) (defn authorize-medical-treatment! [patient-id treatment-id] ...) (defn launch-missiles! [munition-type target-coordinates] ...)
Maybe more concretely, consider a naive implementation of a function that accepts Twitter usernames and returns the number of followers of the named user:
(require 'clojure.xml) (defn twitter-followers ...