inout and function/delegate parameters

Timon Gehr timon.gehr at gmx.ch
Tue Mar 6 02:11:34 PST 2012


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.









More information about the Digitalmars-d mailing list