Using inout in delegates
Steven Schveighoffer
schveiguy at yahoo.com
Fri Oct 5 07:32:15 PDT 2012
On Thu, 04 Oct 2012 09:49:48 -0400, Jacob Carlborg <doob at me.com> wrote:
> void foo (inout int[] arr)
> {
> auto a = { auto b = arr[0]; };
> }
>
> void main ()
> {
> auto a = [3, 4, 5];
> foo(a);
> }
>
> Compiling the above code with DMD 2.060 results in the following error
> message:
>
> Error: variable main.foo.__lambda1.b inout variables can only be
> declared inside inout functions
> Failed: /Users/jacob/.dvm/bin/dvm-current-dc -v -o-
> '/Users/jacob/development/d/main.d' -I'/Users/jacob/development/d'
> >/Users/jacob/development/d/main.d.deps
>
> Is this a bug, a limitation of inout/delegate or am I doing something
> else wrong?
It is a quirk of how inout is implemented. There are definitely some very
tricky situations that inout has uncovered, and I think not all of them
are handled gracefully.
In my first vision for inout, I posited that inout variables should only
be valid within inout functions. No point in declaring inout variables if
you don't have inout parameters or return values, right? I mean the point
of "in out" means what you get in is what you put out. So if you aren't
using a wildcard on an input or output, there is no point of having an
inout variable that can't be transferred anywhere.
But logically, inout is simply another form of const. One that acts like
immutable, but could refer to mutable data. Declaring something inout
inside a non-inout function is useless, but not harmful. I think now, it
should be allowed, because it's more useful to use auto in these
situations, and IFTI goes into fits if you don't allow it.
However, your case is interesting. A delegate is a function, and
functions which are inout have the special feature of transferring const.
In this case, you are pulling the data from the context pointer, not from
a parameter. But the inout for your delegate may be a *different* inout
than the one in your parameter.
Here is a more demonstratable case:
void foo(inout int* a)
{
int x;
inout(int) * foosub(inout(int) * b)
{
inout(int) *result = a > b ? a : b;
return result;
}
int *n = foosub(&x);
}
Note that n could end up being equal to a! Which means we have
effectively removed the inout qualifier from it (very bad). I don't even
know if the above compiles, but I suspect it does.
There is a very confusing aspect of inout. When inout is inside a
function, it's actual type is based solely on the function call itself.
It actually should be that a and b above have *different* unassignable
types. But it is very difficult and confusing thing to understand and
implement, much less explain.
I think at some point, inout needs another overhaul before it is truly a
complete feature.
-Steve
More information about the Digitalmars-d-learn
mailing list