Pure functions and delegates

Timon Gehr timon.gehr at gmx.ch
Wed Jan 18 07:53:12 PST 2012

On 01/18/2012 04:40 AM, H. S. Teoh wrote:
> So, I was quite impressed with D's pureness system, and was
> experimenting a bit with it. Then I discovered that delegates are
> impure, which seems reasonable since there's no way to know what a
> delegate might do. But *if* the compiler verifies that a particular
> delegate is (weakly) pure in the context of the function that passed it,
> then couldn't the function that it gets passed to be declared pure as
> well?
> The context is this:
> 	class MyCollection {
> 		...
> 		void opApply(int delegate(const ref int n) cb) const {
> 			...
> 			if (cb(...)) { ... }
> 			...
> 		}
> 		...
> 		int[] enumerate() {
> 			int[] list;
> 			foreach (n; this) {
> 				list ~= n;
> 			}
> 			return list;
> 		}
> 	}
> Is there a way to convince the compiler that enumerate() can be marked
> 'pure' even though opApply() can't, in general, be pure because it
> doesn't know what the delegate does?
> Technically, enumerate() is weakly pure, because its delegate does not
> touch anything outside of its scope, and given this particular delegate,
> opApply() also is weakly pure. In other words, opApply()'s pureness
> depends on the delegate passed to it. So if there was a way for the
> compiler to check that yes, opApply() is (weakly) pure except for the
> part that calls the delegate (perhaps using some kind of "conditionally
> pure" attribute?), then it should, in theory, be possible to verify that
> yes, the delegate that enumerate() passes to opApply() does not violate
> pureness, so enumerate() can be labelled 'pure'.
> The trouble is, given the current state of things, there is no way to
> implement enumerate() in a pure way, short of duplicating most of
> opApply()'s code and substituting the line that calls the delegate.
> Which is a rather ugly workaround. But otherwise, MyCollection cannot be
> used inside a (strongly) pure function unless it avoids using opApply()
> and enumerate() altogether, even if the container never escapes the pure
> function's scope. This is quite a major limitation IMHO.
> T

I see two distinct issues here:


int foo(int delegate(int) dg,x){return dg(x);}
int bar(int x)pure{foo(x=>x,x);} // error but would be ok


int foo(int x)pure{
     int x;
     (y=>x=y)(2); // error but would be ok
     return x;

1. could be resolved by a simple purity wildcard, in the lines of inout. 
(auto pure? =))
2. could be resolved by extending the weakly pure rule to the context 
pointer of nested functions. Nested functions and delegates would need 
to be able to be declared 'const'. (indicating that they are not allowed 
to mutate anything through the context pointer.) delegate literals and 
nested template function instantiations would need const inference.

More information about the Digitalmars-d-learn mailing list