inout and function/delegate parameters

Steven Schveighoffer schveiguy at yahoo.com
Mon Mar 5 14:31:40 PST 2012


On Mon, 05 Mar 2012 11:17:41 -0500, Stewart Gordon <smjg_1998 at yahoo.com>  
wrote:

> On 05/03/2012 13:49, Steven Schveighoffer wrote:
>> On Sat, 25 Feb 2012 09:02:47 -0500, Timon Gehr <timon.gehr at gmx.ch>  
>> wrote:
> <snip>
>>> inout means 'some qualifier but we don't know which one'. The call  
>>> site on the other
>>> hand knows which qualifier it is. If the call is made to work there is  
>>> no 'making it
>>> mutable', because it is mutable all the time. The inout function  
>>> cannot change the data
>>> because it cannot know what the constancy is.
>>
>> What you would propose is that a delegate which takes a  
>> const/mutable/immutable implicitly
>> translates to one which takes an inout. I agree it can be made to work,  
>> but it does not
>> fit into the current definition of inout.
>
> I'm not sure if you understand correctly.  Is isn't a matter of implicit  
> conversion of delegates from one type to another, but a matter of (in  
> this case) opApply accepting a delegate with a parameter whose constancy  
> matches that of this.

I understand the problem and the proposed solution quite well.

>> It would be ideal for inout to solve this, but it's not chartered in  
>> such a way to do so.
>
> If I'm not mistaken, inout isn't chartered to do anything particular  
> when it occurs in a function signature nested within another.  The spec  
> just leaves it ambiguous.

No, inout is not modifiable during the function execution.  Given the  
transitivity of const and immutable, inout itself must also be transitive.

Think about it this way:

inout(int)* foo(inout(int)* x)
{
    // begin here, at this point x is not modifiable
    // *x = 5; // not allowed!
    return x;
    // end here, at this point inout reverts back to it's original  
constancy (including return value).
}

The original definition I used for inout was "scoped const", meaning it's  
const within the scope and reverts back after the scope.  I did not plan  
for having the constancy "temporarily" revert back to the original  
constancy.  What you wish for is this to take a delegate which matches the  
constancy of the x parameter:

inout(int)* foo(inout(int) *x, void delegate(inout(int)* p) dg)
{
    dg(x); // valid, since the type matches
    return x; // oops, now x could have changed!  Even through it's an  
inout reference!
}

>
>> It's currently transitive, and this would break transitivity. If we  
>> want to look at
>> fundamentally redefining inout so that it can break transitivity, then  
>> we can look at
>> that. But I don't think this is a simple "add-on" to the current  
>> functionality.
> <snip>
>
> Can you give an example of how it breaks transitivity?

Using the above foo function:

void main()
{
    void bar(int *x) {*x = 5;}
    int i = 2;
    foo(&i, &bar); // this sets i to 5 via the inout reference we pass into  
it.
}

In other words, inout is transitively not constant during the function  
call.

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.

-Steve


More information about the Digitalmars-d mailing list