Imperative programming is known for employing side effect to make programs function. Functional programming in turn is known for its minimization of side effects.
integer function rt(integer x)
begin
return x + 1;
end
So, how is this a bad thing? Well let's say we want to do some reasoning about the following chunk of code:
This however will work for
Therefore we can reason about our code which will lead to more robust programs, the possibility of finding bugs that we couldn't hope to find by testing, and even the possibility of seeing opportunities for optimization.Terminology
A function that uses side-effects is referred to as referentially opaque, and one that doesn't is called referentially transparent. For simplicity's sake, we say that a referentially transparent function is one that,
given the same parameters, will always return the same result.Example
As an example, let's use two functions, one which is referentially opaque,
and the other which is referentially transparent: globalValue = 0;
integer function rq(integer x)
begin
globalValue = globalValue + 1;
return x + globalValue;
end
Now, rt
is referentially transparent, which means that rt(x) = rt(x)
as long as x
is the same value. For instance, rt(6) = rt(6) = 7, rt(4) = rt(3+1) = 5
, and so on. However, we can't say any such thing for rq
because it uses a global value which it modifies. integer p = rq(x) + rq(y) * (rq(x) - rq(x));
Now, right off-hand, one would be tempted to simplify this line of code to: integer p = rq(x) + rq(y) * (0) =
integer p = rq(x) + 0 =
integer p = rq(x);
However, this will not work for rq()
because rq(x)
does not equal rq(x)
! Remember, that the return value of rq
is based on a global value which isn't passed in and which gets modified all over the place. This goes against common sense since anything minus itself should be zero.rt
, because it is a referentially transparent function.