On Thursday, 15 May 2014 at 09:23:00 UTC, Jonathan M Davis via
Digitalmars-d wrote:
functions that weren't pure. It allowed for mutation within the
function, and
it allowed for allocation via new, but from the outside, the
function _was_
functionally pure.
If it didn't return the memory allocated with new and if the call
to new resulted in an exception, yes.
It just didn't work.
That I question. A pure function (
http://en.wikipedia.org/wiki/Pure_function ) depends on the
values of the parameters, and only that. That is most useful.
Those value can be very complex. You could have a pure member
function look up values in a cache. Then the configuration of
entire cache is the value.
You need to think about this in terms of pre/post conditions in
Hoare Logic (which I am not very good at btw).
So, Don introduced the idea of "weak" purity. What it comes
down to is that
it's an extension of the concept that mutation within a pure
function is fine
just so long as its arguments aren't mutated. We made it so
that pure
functions _didn't_ have to have immutable parameters. They just
couldn't
access anything that wasn't passed to them as arguments. This
meant that they
could only mutate what they were given and thus they didn't
violate the
"strong" purity of the original pure function which had
immutable parameters.
And that's fine as long as nobody else is holding a reference to
those mutable parameters. That means that you are taking version
N of the mutable and returning version N+1. That's similar to
x=1
a =f(x)
x=x+1
b = f(x)
which can be rewritten as:
x0 =1
a = f(x0)
x1 = x0+1
b = f(x1)
If you think in terms of a context for purity such as a
transaction then you can even allow access to globals as long as
they remain constant until the transaction is committed (or you
leave the context where purity is desired). Meaning, you can
memoize within that context.
functions that called it), but we do need that guarantee. The
result is that
the pure attribute doesn't in and of itself mean functional
purity anymore,
but it _can_ be used to build a function which is functionally
pure.
But, that can be deduced by the compiler, so what is the point of
having "pure" for "weakly pure"? Clearly you only need to specify
"strongly pure"?
So, sorry that it offends your sensibilities that pure by
itself does not
indicate functional purity, but it's a building block for
functional purity,
It doesn't offend me, but it is a source of confusion and not
sticking to definitions makes the language design look random.
The same thing goes for lazy parameters. Why pick Call-By-Name
(Algol style) over Call-By-Need (memoing)? Call-By-Name is known
to be error prone.
Actually, lazy parameters should be restricted to pure
expressions… if correctness and safety is the goal.
attribute for this. And even if pure _didn't_ enable functional
purity, it
would still be highly useful just from the fact that a pure
function (be it
weak or strong) cannot access global variables, and that makes
it _much_
easier to reason about code, because you know that it isn't
accessing anything
that wasn't passed to it.
Ok, but maybe the opposite would be better. Marking functions
that access globals with @global or something. After all, most
functions don't access globals.