Pure Functions / Intro to JavaScript ES6 programming, lesson 17


You have created plenty of functions already,
and most of them work like this: take some arguments, calculate something using the arguments,
return the answer. Your functions, even those that use other functions, are nice in this
way: they are predictable, stable. For example, the surface area function you made in the
beginning: give it a number and it will return a number. Give the same number again — you’ll
get the same result. In fact, no matter how many times you’re going to repeat the call,
you’ll get the same result for the same input. While calculating the return value, this function
doesn’t take into account anything else, only the argument. It doesn’t care what time it
is, what weather it is, what other functions are working in the program, what values are
there in some variables outside. Functions like this are called deterministic. This word comes from physics and philosophy.
A detirministic system is something that produces the same output from a given starting condition.
Some philosophical theories explore the idea that reality follows a predetermined path,
and everything happens the way it happens because it couldn’t happen otherwise. There
is no free will, and you were destined to watch this video today. Anyway, let’s back up. In the context of programming,
a deterministic function is a function which will always produce the same output for a
particular input. You might be wondering how else a function
can behave. Well, a non-deterministic function is not easily predictable, and its output
depends on something else. For example, think of a function that takes
a zip code and returns the current weather. It’s probably connecting to a weather server
via internet and gives different answers at different times, because, well, the weather
changes. An even simpler example would be a random
number generator. Usually, any programming language has some built-in way to generate
random numbers. In JavaScript it looks like this: As you see, every time you call it with the
same arguments (in this case — no arguments at all) — the output is new. This function
is non-deterministic, but that’s the whole point. A random number generator should give
you different numbers by definition, even though the calls look the same. Deterministic functions are better in many
ways, but not all functions can be deterministic, and that’s okay. A good rule of thumb is — if
a function can be deterministic, then it should be. Deterministic functions are predictable, less
fragile and they are easier to think about. Using them is easier too, constructing complex
structures and programs. Since deterministic functions always produce
the same output for the same input, they can be optimized: they can remember the output
for a certain input, and the next time this input comes in — just return the remembered
value instead of doing the whole computation over again. This is guaranteed to be okay
if the function is deterministic. We have to touch one more idea before talking
about the most beautiful and nice type of functions. There is a notion of side effects:
how a function changes the outside world. That example above — `surfaceAreaCalculator`
function — doesn’t have any side effects. It doesn’t change anything outside its boundaries. Your good friend `console.log` function has
a side effect: it prints something onto the screen. This screen thing is definitely outside
the function, it’s the computer, the world where the function lives. Or, consider the following code: Function `f` changes the value of a global
variable `a`. This variable is in the outside world from the function’s point of view, and
function `f` changes it. So, `f` has side effects. Again, this is not bad, after all, a program
without side effects will not be useful. We want our programs to do something, to somehow
change the world — show something on the screen, make a noise, send an email, etc.
But it’s possible to minimize side effects in your functions and programs, and it’s a
good idea, really. While both `f` and `console.log` have side-effects,
they are deterministic. `f` always returns `true`, and `console.log` always returns `undefined`.
The things functions return have nothing to do with the way they affect the outside world. Do not confuse printing and returning. Printing
onto the screen is just an action, this is what `console.log` does. But it also returns
a value — it always returns `undefined`. If `f` returned the value of `a` instead of
`true`, then it would be a non-deterministic function with side effects: You can never be sure about what value `f`
will return until you know something else. It depends on some outside factor, namely,
the current value of `a`. Fewer side effects a function has — the
better. When a function has no side effects and is
deterministic — we call it a “pure” function. It’s so predictable, clean and transparent.
In this way, pure functions are close to the functions in math. x square will always give
the same result for the same value of x, and computing square of x doesn’t change x itself. Everything about pure functions screams “easier”:
they are easier to read, easier to debug, easier to test. Pure functions in a system
do not depend on anything else by definition, so the order they are called in doesn’t matter.
This means it’s easy to make them work in parallel, for example, simultaneously on different
processors or even different computers. Pure functions live in a timeless realm. The
whole notion of time, of actions happening in some order, doesn’t apply to pure functions.
They don’t care about time. When you look at pure functions, read the code, debug, test
or use just them — you don’t have to think about time, about what happened before and
will happen after. This is liberating, and all the “easier” things about pure functions
are consequences of this fact. Non-determinism and side effects add the notion
of time. If your function depends on something that might or might not happen and changes
something outside its walls, then it suddenly becomes dependent on time. It now matters
when in time does this function call happen. It becomes harder to think and test and work,
because you have an additional dimension to consider.

Leave a Reply

Your email address will not be published. Required fields are marked *