The benefit is that pure functions make your code easier to reason about. Or, in another words, side effects increase the complexity of your code.
Take an example of
A pure method would ask you for a product quantity, a currency, etc. You know that whenever the method is called with the same arguments, it will always produce the same result.
- You can even cache it and use the cached version.
- You can make it lazy and postpone its call to when you actually need it , knowing that the value won't change meanwhile.
- You can call the method multiple times, knowing that it won't have side effects.
- You can reason about the method itself in an isolation from the world, knowing that all it needs are the arguments.
A non-pure method will be more complex to use and debug. Since it depends on the state of the variables other than the arguments and possibly altering them, it means that it could produce different results when called multiple times, or not have the same behavior when not called at all or called too soon or too late.
Imagine there is a method in the framework which parses a number:
decimal math.parse(string t)
It doesn't have referential transparency, because it depends on:
The environment variable which specifies the numbering system, that is Base 10 or something else.
The variable within the
math library which specifies the precision of numbers to parse. So with the value of
1, parsing the string
"12.3456" will give
The culture, which defines the expected formatting. For instance, with
"12.345" will give
12345, because the separation character should be
Imagine how easy or difficult would it be to work with such method. With the same input, you can have radically different results depending on the moment when you call the method, because something, somewhere changed the environment variable or switched the culture or set a different precision. The non-deterministic character of the method would lead to more bugs and more debugging nightmare. Calling
math.parse("12345") and obtaining
5349 as an answer since some parallel code was parsing octal numbers isn't nice.
How to fix this obviously broken method? By introducing referential transparency. In other words, by getting rid of global state, and moving everything to the parameters of the method:
decimal math.parse(string t, base=10, precision=20, culture=cultures.en_us)
Now that the method is pure, you know that no matter when you call the method, it will always produce the same result for the same arguments.