On Tue, 21 Sep 2010 22:21:39 -0400, Don <nos...@nospam.com> wrote:
The docs currently state that:
---
Pure functions are functions that produce the same result for the same
arguments. To that end, a pure function:
* has parameters that are all immutable or are implicitly
convertible to immutable
* does not read or write any global mutable state
---
This is extremely restrictive, and not currently enforced.
Two specific limitations:
- a 'pure' member function doesn't really make sense (could only be
called on an immutable class)
- a pure function cannot have 'out' parameters.
In a discussion on D.learn, Steven Schveighoffer noted that it's only
shared variables which make things complicated.
The limitations exist because 'pure' is used to mean both 'no hidden
state' AND 'cachable'. But 'cachable' is really only an implementation
detail.
PROPOSAL:
Drop the first requirement. Only one requirement is necessary:
A pure function does not read or write any global mutable state.
If a pure function has parameters that are all immutable or are
implicitly convertible to immutable, then the compiler is permitted to
cache the results.
This is possible because the first rule (all immutable parameters) is
trivial, and can be checked from the function declaration (in fact, you
can check it just from the mangled function name). The second rule (no
globals) is viral, and requires inspection of the function body, and the
function bodies of every function called by that function.
Actually, a clever compiler could even cache the results of pure
functions which have parameters which don't implicitly cast to immutable.
I haven't found anything in TDPL which mentions the "only immutable
parameters" rule. Relaxing that rule would allow much larger functions
to be cached. The more important benefit (IMHO) of pure, that it makes
it easier to reason about code, would be dramatically extended.
One of the major benefits of functional languages (a.k.a pure functions)
is that you can automatically parallelize them (i.e. via a task based
runtime) in addition to caching the result. I really don't want to lose
that guarantee. However, I do see your point. One of the benefits of D's
pure functions is the ability to use procedural code inside them; however
the "does not read or write any global mutable state" prevents pure
functions from calling impure functions/members on their internal (impure)
variables. So removing the concurrency safety from pure would greatly
expand the number of pure functions, however, automatic parallelism would
be lost. I don't view this as an acceptable reduction in pure's power,
particularly given that Dave's std.parallelism module is currently under
review.
With regard to an alternative, I think two levels of pure have been
identified as being useful and synergistic to each other. I think this
could either manifest itself as pure + scope(pure) or as a new 'task' type
+ pure. Anyways, that's my two cents worth.