Delegate Literals + Immutability, pure and closures

dsimcha dsimcha at yahoo.com
Thu Sep 29 13:32:45 PDT 2011


Immutability and type propagation are two of D's greatest assets.  Below is an
example of where they would be difficult to take advantage of:

int foo;
if( bar < 3) {
    try {
        foo = doStuff(someOtherStackVariables);
    } catch(SomeException) {
        foo = 666;
    }
} else {
    foo = 4;
}

I've recently discovered this pattern to allow use of type propagation and
immutability in these situations with no extra boilerplate:

immutable foo = {
    if( bar < 3) {
        try {
            return doStuff(someOtherStackVariables);
        } catch(SomeException) {
            return 666;
        }
    } else {
        return 4;
    }
}();

This allows me to make foo immutable and have its type inferred while avoiding
any boilerplate code, but has four problems:

1.  It allocates a closure.  Therefore, it can't be used in
performance-critical code.  We really need to optimize away closure allocation
in trivial cases where the function pointer obviously can't escape, to make
delegate literals more useful in performance-critical code.

2.  Delegate literals can't be inlined in even the most trivial cases.  This
is less severe than (1), and probably would almost never have a non-negligible
impact in practice, though.

3.  A function that uses a delegate literal can't be pure because purity is
not inferred for delegate literals:

void main() {
    foo();
}

void foo() pure {
    int z;
    int i = {return z + 1;}();
}

Error: pure function 'foo' cannot call impure delegate '__dgliteral1'

4.  Auto return type inference is limited to cases where all return statements
return the exact type.  Is there any reason I'm missing why, if multiple
return statements with different types are present, an auto return function
couldn't just return a common type?


More information about the Digitalmars-d mailing list