DIP25 draft available for destruction

Zach the Mystic reachBUTMINUSTHISzach at gOOGLYmail.com
Wed Feb 6 07:38:32 PST 2013


On Wednesday, 6 February 2013 at 07:38:17 UTC, Andrei 
Alexandrescu wrote:
> Probably it'll need a fair amount of tweaking. Anyhow it's in 
> destroyable form.
>
> http://wiki.dlang.org/DIP25
>
>
> Thanks,
>
> Andrei

All of the 'fine' ones are fine. Which leaves how one might 
invoke the 'unfine' ones. The language must make a choice between 
restricted simplicity and flexible complexity. If it chooses 
flexibility, the function signature must give a clue as to what 
the return value contains. 'out' return values and 'scope' 
parameters will give the clues it needs.

Here are all the 'unfine' functions listed:

ref T gun(ref T);
struct S { int a; T b; }
ref S iun(ref S);

ref T caller(bool condition, ref T v1, ref S v2, T v3, S v4) {
     T v5;
     S v6;

     // Not fine, bound to locals
     // if (condition) return gun(v3);
     // if (condition) return gun(v4.b);
     // if (condition) return gun(v5);
     // if (condition) return gun(v6.b);

     // Not fine, bound to locals
     // if (condition) return iun(v4);
     // if (condition) return iun(v6);
}

Say gun's actual implementation is:

ref T gun(ref T a) {
    auto noo = new T;
    noo = a;
    return noo;
}

You can' tell from the function signature that the return value 
of this function is good to go, so the call 'return gun(v3);' 
above would be disallowed even though it didn't need to be. If 
you marked the signature with 'out', the caller knows it's good 
to go, and the compiler can statically prevent the function from 
returning one of its ref parameters. 'out' can be made to imply 
'ref' in any case where the type is not inherently a reference 
anyway.

out T gun(ref T a) {
    return new T; // Pass
    return a; // Error
}

This will solve all problems, except for the very rare corner 
case when you need to assert fined-grained control over exactly 
which ref parameters are safe and which are not. 'scope' comes to 
the rescue here.

ref int fud(ref int a, scope int b) {
    a += b;
    return a; // Pass

    return b; // Error
}
ref int elmer(ref int f) {
    int v;
    return fud(f, v); // Passes
    return fud(v, f); // Fails
}

An 'out' return value simply marks all its 'ref' parameters 
'scope' underneath the hood, so there will never be a need for 
both 'out' and 'scope' in the same signature. Since 'scope' is 
useless if its not a reference, it implies 'ref' also.

I'm pretty sure this is the best way to make the language 
completely flexible. I don't anticipate an easier way to get it 
done, and therefore, to my mind at least, the choice is between 
simple-but-limited and flexible-and-complicated.


More information about the Digitalmars-d mailing list