pure
has been expanded a bit since the release of TDPL, since pure
as TDPL describes turns out to be far too restrictive to be useful beyond simple math functions and the like. You can look at the online documentation for the current definition, but it essentially comes down to this:
pure
functions cannot access any module-level or static variables which can be mutated during the course of the program (they must be const
value types or immutable
to be accessed from a pure
function).
pure
functions cannot call any functions which are not pure
.
pure
functions cannot perform I/O.
That's it. There are no other restrictions. However, there are additional restrictions required if a pure
function is going to be optimized such that it only gets called one time even if it's used multiple times within a statement. Namely:
- The function's parameters must be
immutable
or implicitly convertible to immutable
.
In theory that could be expanded to requiring that the function's arguments must be immutable
or implicitly convertible to immutable
(so that a function with const
parameters could be optimized when it's given immutable
arguments), but that's not currently the case.
Such pure
functions are sometimes referred to as "strongly" pure
, whereas those which cannot be optimized would be referred to as "weakly" pure
. TDPL describes strongly pure
functions. Weakly pure
functions were added in order to make pure
more generally usable.
While weakly pure
functions can alter their arguments, they cannot alter the global state, so when they're called by strongly pure
functions (which can't alter their arguments), the guarantee that the strongly pure
function's return value will always be the same for the same arguments still holds. Essentially, because the weakly pure
functions cannot mutate global state, they're part of the private state of the strongly pure
function that they're called from. So, it's very much in line with what Andrei describes in section 5.11.1.1 pure
is as pure
Does in TDPL, except that the private state of the function has been expanded to allow functions which can alter its private state without altering global state.
Another major thing of note which has been added since TDPL with regards to pure
is function attribute inference. pure
, nothrow
, and @safe
are inferred for templated functions (though not for normal functions). So, if a templated function can be pure
, now it is pure
. Its purity depends on what it's instantiated with. So, it becomes possible to use pure
with templated functions, whereas before, you usually couldn't, because if you made it pure
, it wouldn't work with an impure function. But if you didn't make it pure
, then you couldn't use it with a pure
function, so it was a major problem for pure
. Fortunately, attribute inference fixes that now though. As long as a templated function follows the rules listed above when it's instantiated, then it's considered pure
.