On 03/05/2012 11:31 PM, Steven Schveighoffer wrote:
On Mon, 05 Mar 2012 11:17:41 -0500, Stewart Gordon <[email protected]>
wrote:
On 05/03/2012 13:49, Steven Schveighoffer wrote:
On Sat, 25 Feb 2012 09:02:47 -0500, Timon Gehr <[email protected]>
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).
}
I don't think this is the best way to think about inout. Try to think
about it as if the constancy was determined, but unknown. It does not
actually change, the function just does not know what it is because it
has to work in a polymorphic way.
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!
}
Well, that can happen even for const references. What is your point?
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.
Because it has been matched as *mutable*. There is no issue.
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.