Thread overview | |||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
October 04, 2012 Using inout in delegates | ||||
---|---|---|---|---|
| ||||
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? -- /Jacob Carlborg |
October 04, 2012 Re: Using inout in delegates | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | On Thursday, 4 October 2012 at 13:55:39 UTC, Jacob Carlborg 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?
IIRC, inout must be applied to the return type too, and it only works in templates.
|
October 04, 2012 Re: Using inout in delegates | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jesse Phillips | On 10/04/2012 07:09 AM, Jesse Phillips wrote: > On Thursday, 4 October 2012 at 13:55:39 UTC, Jacob Carlborg 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? > > IIRC, inout must be applied to the return type too, and it only works in > templates. inout is like a template on 'mutable', const, and immutable; but it need not be applied to templates. Here is a simple example that transfers the mutability to the return type: http://ddili.org/ders/d.en/function_parameters.html inout(int)[] trimmed(inout(int)[] slice) { if (slice.length) { --slice.length; // trim from the end if (slice.length) { slice = slice[1 .. $]; // trim from the beginning } } return slice; } All three blocks below compile: { int[] numbers = [ 5, 6, 7, 8, 9 ]; // The return type is slice of mutable elements int[] middle = trimmed(numbers); middle[] *= 10; writeln(middle); } { immutable int[] numbers = [ 10, 11, 12 ]; // The return type is slice of immutable elements immutable int[] middle = trimmed(numbers); writeln(middle); } { const int[] numbers = [ 13, 14, 15, 16 ]; // The return type is slice of const elements const int[] middle = trimmed(numbers); writeln(middle); } inout can also be applied to member functions where the 'this' reference takes the mutability of a parameter and all of the member accesses becomes mutable, const, or immutable. Ali |
October 05, 2012 Re: Using inout in delegates | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jesse Phillips | On 2012-10-04 16:09, Jesse Phillips wrote: > IIRC, inout must be applied to the return type too, and it only works in > templates. What? The whole point of "inout" is to NOT have to use templates since the compiler will generate the same code anyway. http://dlang.org/function.html#inout-functions I also tried to make it a template but I get the same result. Actually in my original code it's a template. -- /Jacob Carlborg |
October 05, 2012 Re: Using inout in delegates | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On 2012-10-04 16:18, Ali Çehreli wrote: > inout is like a template on 'mutable', const, and immutable; but it need > not be applied to templates. Here is a simple example that transfers the > mutability to the return type: I do think I understand how "inout" works, or at least I thought. I don't understand how the delegate affects anything. If I remove the delegate to this code it compiles: void foo (inout int[] arr) { auto a = arr[0]; } My actual problem is that I want to be able to pass both mutable, const and immutable to a function. In that function I want the "mutability" to persist. I first used const for my function and that works, kind of. The problem if I do like this: void foo (const int[] arr) { auto s = typeid(typeof(arr)).toString; // here "s" will be something like "const(const(int)[])" } I doesn't matter if I pass immutable or mutable, "s" will always be "const(const(int)[]". So I thought, "hey, that's what inout is for, I use that", then everything blows up. I'm using "typeid(typeof(arr))" in my serialization library to get a string representation of a type. I would prefer that the mutability was correct. -- /Jacob Carlborg |
October 05, 2012 Re: Using inout in delegates | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | On 10/04/2012 11:30 PM, Jacob Carlborg wrote:
> On 2012-10-04 16:18, Ali Çehreli wrote:
>
>> inout is like a template on 'mutable', const, and immutable; but it need
>> not be applied to templates. Here is a simple example that transfers the
>> mutability to the return type:
>
> I do think I understand how "inout" works, or at least I thought. I
> don't understand how the delegate affects anything. If I remove the
> delegate to this code it compiles:
>
> void foo (inout int[] arr)
> {
> auto a = arr[0];
> }
>
> My actual problem is that I want to be able to pass both mutable, const
> and immutable to a function. In that function I want the "mutability" to
> persist.
>
> I first used const for my function and that works, kind of. The problem
> if I do like this:
>
> void foo (const int[] arr)
> {
> auto s = typeid(typeof(arr)).toString;
> // here "s" will be something like "const(const(int)[])"
> }
>
> I doesn't matter if I pass immutable or mutable, "s" will always be
> "const(const(int)[]". So I thought, "hey, that's what inout is for, I
> use that", then everything blows up.
>
> I'm using "typeid(typeof(arr))" in my serialization library to get a
> string representation of a type. I would prefer that the mutability was
> correct.
>
This workaround makes the compiler happy:
void foo (inout(int)[] arr)
{
auto a = (inout int) { auto b = arr[0]; };
}
But probably not what you want. :/
IIRC, inout has bugs and incomplete implementation. I think this should be in the bug database.
Ali
|
October 05, 2012 Re: Using inout in delegates | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | On Thu, 04 Oct 2012 09:49:48 -0400, Jacob Carlborg <doob@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
|
October 06, 2012 Re: Using inout in delegates | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On 2012-10-05 16:09, Ali Çehreli wrote: > > This workaround makes the compiler happy: > > void foo (inout(int)[] arr) > { > auto a = (inout int) { auto b = arr[0]; }; > } > > But probably not what you want. :/ > > IIRC, inout has bugs and incomplete implementation. I think this should > be in the bug database. Hmm, I'll see if I can use that, thanks. -- /Jacob Carlborg |
October 07, 2012 Re: Using inout in delegates | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On 2012-10-05 16:09, Ali Çehreli wrote: > This workaround makes the compiler happy: > > void foo (inout(int)[] arr) > { > auto a = (inout int) { auto b = arr[0]; }; > } > > But probably not what you want. :/ > > IIRC, inout has bugs and incomplete implementation. I think this should > be in the bug database. Using the above workaround did make it compile. But using typeid it now contains "inout" instead. It turns out I didn't need neither "const" or "inout", don't know why I added it in the first place. Thanks anyway. -- /Jacob Carlborg |
October 08, 2012 Re: Using inout in delegates | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On 10/05/2012 04:09 PM, Ali Çehreli wrote:
> ...
>
> This workaround makes the compiler happy:
>
> void foo (inout(int)[] arr)
> {
> auto a = (inout int) { auto b = arr[0]; };
> }
>
> But probably not what you want. :/
>
> IIRC, inout has bugs and incomplete implementation. I think this should
> be in the bug database.
>
> Ali
The original behaviour is to be expected and the workaround exploits a compiler bug.
The correct way to get rid of the compile error is:
void foo(inout(int)[] arr){
auto a = { const b = arr[0]; } // or int b = arr[0];
}
|
Copyright © 1999-2021 by the D Language Foundation