On 03/06/2012 12:27 AM, Steven Schveighoffer wrote:
...

There are two parts to inout, one is that it can be one function called
3 different ways, the other is that you know it's constant during
function execution. Some people like that second part, even if it
doesn't fully guarantee everything. I.e. there's a reason people use
const in C++ besides it being trendy.


By passing a delegate that changes an inout-matched argument it is made explicit that inout data may change. Technically, none of the existing guarantees are lost, we just add some expressiveness to the type system.



I'm not saying we cannot bend the rules to allow for this, because
clearly it doesn't violate the "true" constancy type of the data passed
in, but I don't think it's a straightforward change conceptually. I'm
not a compiler writer, so I don't know how this works in their minds,
I'd like to have their input.

Implementation of what you propose should be quite simple. The issue
is with the design, i.e. allowing both tying the inout in the delegate
parameter signature to the inout in the enclosing signature and having
an independent inout delegate parameter needs workable syntax.

I think it can be done:

1. determine inout match based on existing rules, excluding delegate
parameters.
2. change delegate parameter inouts to matched value.
3. Use implicit delegate conversion (using contravariance) to allow
passing delegates of proper type.

For example:

void foo(inout(int)* x, void delegate(inout(int)* y) dg);

void main()
{
int mx;
immutable int ix;
const int cx;

void bar1(int *mp) {}
void bar2(immutable(int) *ip) {}
void bar3(const(int) *cp) {}
void bar4(inout(int) *iop) {}

// inout matched as mutable due to mx, signature becomes void foo(int
*x, void delegate(int *y) dg);
foo(&mx, &bar1); // fine, direct match of both parameters
foo(&mx, &bar2); // not fine, immutable delegate does not implicitly
convert to mutable
foo(&mx, &bar3); // fine, const delegate can implicitly convert to mutable
foo(&mx, &bar4); // fine, inout delegate can implicitly convert to mutable

// signature becomes void foo(immutable(int) *x, void
delegate(immutable(int) *y) dg);
foo(&ix, &bar1); // error
foo(&ix, &bar2); // ok
foo(&ix, &bar3); // fine, const delegate can implicitly convert to
immutable
foo(&ix, &bar4); // fine, inout delegate can implicitly convert to
immutable

// signature becomes void foo(const(int) *x, void delegate(const(int)
*y) dg);
foo(&cx, &bar1); // error
foo(&cx, &bar2); // error
foo(&cx, &bar3); // ok
foo(&cx, &bar4); // ok

// etc...
}

I understand, but how would you support this use case?:

inout(int)[] foo(inout(int)[] delegate(inout(int)[] dg), inout(int)[] arr){
    int[] x = dg(new int[16]);
    immutable(int)[] y = dg(new immutable(int)[16]);
    // ...
    inout(int)[] z = dg(arr);
    return foo(z,y,z);
}

In essence, it should be possible to pass an inout delegate to an inout function, such that the function can use the delegate as an inout delegate.



Note that Walter has explicitly rejected contravariance conversion for
delegates.

That is unfortunate.

You have good persuasive skills, maybe you can help :) See
bug http://d.puremagic.com/issues/show_bug.cgi?id=3180 and
http://d.puremagic.com/issues/show_bug.cgi?id=3075


IIRC Kenji Hara has already started attempts to loosen the restrictions regarding delegate implicit conversions. Hopefully Walter will reconsider.







Reply via email to