digitalmars.D.learn - Generic collection/element function signatures in D2 versus D1
- Nick Sabalausky (17/17) Sep 04 2010 In D1 I did this sort of thing a fair amount:
- Nick Sabalausky (8/23) Sep 04 2010 Oh, also, and perhaps more importantly (I forgot, this was my main origi...
- Jacob Carlborg (9/35) Sep 04 2010 If you're not going to modify the content of the array I think this will...
- Nick Sabalausky (37/43) Sep 11 2010 On DMD 2.048, This isn't working for me:
- Brad Roberts (2/62) Sep 11 2010 http://d.puremagic.com/issues/show_bug.cgi?id=2594
- Jonathan M Davis (68/88) Sep 04 2010 Okay, here's a shot at it:
- BLS (6/11) Sep 05 2010 I am curious, how this will look and feel once inout is working ?
- Steven Schveighoffer (7/18) Sep 07 2010 inout void doesn't make any sense. You can't have a const void or
- Jacob Carlborg (7/28) Sep 07 2010 inout is only used when you want to return the same constness (mutable,
- Steven Schveighoffer (3/33) Sep 07 2010 Yes, exactly. This is why inout functions cannot return void.
- Pelle (8/42) Sep 07 2010 Hmm.
- Steven Schveighoffer (14/60) Sep 07 2010 Yes, a valid return. Your function should be:
- Pelle (30/43) Sep 07 2010 That's not an equivalent function signature. Or maybe it is, but look at...
- Steven Schveighoffer (14/61) Sep 07 2010 Thanks for clarifying, I didn't quite understand the usage before.
- Steven Schveighoffer (17/80) Sep 08 2010 I realized last night that this won't work. Simple reason -- during an ...
- Pelle (3/86) Sep 08 2010 Well, inout was conceived as a counter to where you need to write the
- Steven Schveighoffer (10/107) Sep 08 2010 Not exactly, it was conceived as a solution for the case where you would...
- Jacob Carlborg (6/53) Sep 07 2010 That won't work, you can't have inout on return of a function without
In D1 I did this sort of thing a fair amount: void foo(T)(T[] collection, T elem) { // Blah, whatever } Worked for any of the string types, worked for any array, or anything with the appropriate opIndexes, and for all I know there may be some improvement that could still be made. But of course, in D2 strings have that extra immutable part that mucks up the above for strings (and then there's ranges), so: Is there a typical generally-best way in D2 to declare a function signature for operating on collections and elements? I know it would involve using the standard range interfaces in the body and choosing the most restrictive range type that gets the job done, and I'm fine with all that, but is there a good example of a typical "best-practice" generic-function signature in D2? ------------------------------- Not sent from an iPhone.
Sep 04 2010
"Nick Sabalausky" <a a.a> wrote in message news:i5su5e$23mk$1 digitalmars.com...In D1 I did this sort of thing a fair amount: void foo(T)(T[] collection, T elem) { // Blah, whatever } Worked for any of the string types, worked for any array, or anything with the appropriate opIndexes, and for all I know there may be some improvement that could still be made. But of course, in D2 strings have that extra immutable part that mucks up the above for strings (and then there's ranges), so: Is there a typical generally-best way in D2 to declare a function signature for operating on collections and elements? I know it would involve using the standard range interfaces in the body and choosing the most restrictive range type that gets the job done, and I'm fine with all that, but is there a good example of a typical "best-practice" generic-function signature in D2?Oh, also, and perhaps more importantly (I forgot, this was my main original reason for even posting the question): What would be the *right* D2 version of the above code that *didn't* bother with ranges, and just stuck with arrays and strings? Sometimes I need to do something in CTFE and using ranges leads to using "std.algorithm", and CTFE still tends to choke on a lot of "std.algorithm".
Sep 04 2010
On 2010-09-04 10:02, Nick Sabalausky wrote:"Nick Sabalausky"<a a.a> wrote in message news:i5su5e$23mk$1 digitalmars.com...If you're not going to modify the content of the array I think this will work: void foo (T) (const(T)[] collection, T elem) {} This will allow both mutable, immutable and const arrays. But it will not let you modify the array like this: collection[3] = 'a'; -- /Jacob CarlborgIn D1 I did this sort of thing a fair amount: void foo(T)(T[] collection, T elem) { // Blah, whatever } Worked for any of the string types, worked for any array, or anything with the appropriate opIndexes, and for all I know there may be some improvement that could still be made. But of course, in D2 strings have that extra immutable part that mucks up the above for strings (and then there's ranges), so: Is there a typical generally-best way in D2 to declare a function signature for operating on collections and elements? I know it would involve using the standard range interfaces in the body and choosing the most restrictive range type that gets the job done, and I'm fine with all that, but is there a good example of a typical "best-practice" generic-function signature in D2?Oh, also, and perhaps more importantly (I forgot, this was my main original reason for even posting the question): What would be the *right* D2 version of the above code that *didn't* bother with ranges, and just stuck with arrays and strings? Sometimes I need to do something in CTFE and using ranges leads to using "std.algorithm", and CTFE still tends to choke on a lot of "std.algorithm".
Sep 04 2010
"Jacob Carlborg" <doob me.com> wrote in message news:i5t61q$2j76$1 digitalmars.com...If you're not going to modify the content of the array I think this will work: void foo (T) (const(T)[] collection, T elem) {} This will allow both mutable, immutable and const arrays. But it will not let you modify the array like this: collection[3] = 'a';On DMD 2.048, This isn't working for me: ----------------------------------------- void foo(T)(const(T)[] coll, T elem) { } void main() { string x = "hello"; foo(x, x[1]); } ----------------------------------------- Result: ----------------------------------------- testStringAndChar.d(8): Error: template testStringAndChar.foo(T) does not match any function template declaration testStringAndChar.d(8): Error: template testStringAndChar.foo(T) cannot deduce template function from argument types !()(string,immutable(char)) ----------------------------------------- I figured that was just because 'const(immutable(T))[]' doesn't make much sence, so I tried this and got the exact same error messages: ----------------------------------------- import std.traits; void foo(T)(const(Unqual!T)[] coll, T elem) { } void main() { string x = "hello"; foo(x, x[1]); } ----------------------------------------- It seems to be a problem with IFTI, because this does work with both versions: foo!char(x, x[1]); Kind of a pain.
Sep 11 2010
On 9/11/2010 9:32 PM, Nick Sabalausky wrote:"Jacob Carlborg" <doob me.com> wrote in message news:i5t61q$2j76$1 digitalmars.com...http://d.puremagic.com/issues/show_bug.cgi?id=2594If you're not going to modify the content of the array I think this will work: void foo (T) (const(T)[] collection, T elem) {} This will allow both mutable, immutable and const arrays. But it will not let you modify the array like this: collection[3] = 'a';On DMD 2.048, This isn't working for me: ----------------------------------------- void foo(T)(const(T)[] coll, T elem) { } void main() { string x = "hello"; foo(x, x[1]); } ----------------------------------------- Result: ----------------------------------------- testStringAndChar.d(8): Error: template testStringAndChar.foo(T) does not match any function template declaration testStringAndChar.d(8): Error: template testStringAndChar.foo(T) cannot deduce template function from argument types !()(string,immutable(char)) ----------------------------------------- I figured that was just because 'const(immutable(T))[]' doesn't make much sence, so I tried this and got the exact same error messages: ----------------------------------------- import std.traits; void foo(T)(const(Unqual!T)[] coll, T elem) { } void main() { string x = "hello"; foo(x, x[1]); } ----------------------------------------- It seems to be a problem with IFTI, because this does work with both versions: foo!char(x, x[1]); Kind of a pain.
Sep 11 2010
On Saturday 04 September 2010 00:57:48 Nick Sabalausky wrote:In D1 I did this sort of thing a fair amount: void foo(T)(T[] collection, T elem) { // Blah, whatever } Worked for any of the string types, worked for any array, or anything with the appropriate opIndexes, and for all I know there may be some improvement that could still be made. But of course, in D2 strings have that extra immutable part that mucks up the above for strings (and then there's ranges), so: Is there a typical generally-best way in D2 to declare a function signature for operating on collections and elements? I know it would involve using the standard range interfaces in the body and choosing the most restrictive range type that gets the job done, and I'm fine with all that, but is there a good example of a typical "best-practice" generic-function signature in D2? ------------------------------- Not sent from an iPhone.Okay, here's a shot at it: import std.algorithm; import std.array; import std.container; import std.stdio; import std.traits; void foo(T, U)(T collection, U elem) if(is(U : Unqual!(typeof(collection[].front)))) { if(elem == collection.front) writefln("%s == %s", elem, collection.front); else writefln("%s != %s", elem, collection.front); } void bar(R, U)(R range, U elem) if(is(U : Unqual!(typeof(range.front)))) { if(elem == range.front) writefln("%s == %s", elem, range.front); else writefln("%s != %s", elem, range.front); } void main() { dstring a = "hello world"; foo(a, 'h'); foo(a, 'g'); bar(a, 'h'); bar(a, 'g'); writeln(); Array!int b; b.insert(1); b.insert(2); b.insert(3); foo(b, 1); foo(b, 2); bar(b, 1); bar(b, 2); writeln(); SList!int c; c.insert(3); c.insert(2); c.insert(1); foo(c, 1); foo(c, 2); bar(c, 1); bar(c, 2); writeln(); auto d = find(c[], 2); bar(d, 1); bar(d, 2); } foo() takes a container type where you can get a range to the whole thing with a slice, and bar() works on ranges. However, it looks like all of the containers in std.container currently implement front(), so both foo() and bar() work on them. Of course, if you doing stuff that isn't on a range, then bar() wouldn't work, and foo() won't work on ranges. So, which you want probably depends on what you're trying to do. A function like bar will work on more but will be restricted to range-base operations only. And depending on what you do in a function like bar(), you might need more template constraints to constrain the type of range. I haven't tried any of this with CTFE, but the function signatures should work just fine with it. Whether you can use CTFE should therefore be a question of what you try to do in the function. In any case, I think that Unqual is the secret sauce that you're looking for here. - Jonathan M Davis
Sep 04 2010
On 05/09/2010 02:16, Jonathan M Davis wrote:void foo(T)(T[] collection, T elem)I am curious, how this will look and feel once inout is working ? inout void foo(T)(inout(T)[] collection, inout T elem) { // Blah, whatever} }{ // Blah, whatever }
Sep 05 2010
On Sun, 05 Sep 2010 09:40:59 -0400, BLS <windevguy hotmail.de> wrote:On 05/09/2010 02:16, Jonathan M Davis wrote:inout void doesn't make any sense. You can't have a const void or immutable void. Now, if foo is a member function, then inout applies to the "this" pointer, but even then, you need a return type other than void for inout to be used. -Stevevoid foo(T)(T[] collection, T elem)I am curious, how this will look and feel once inout is working ? inout void foo(T)(inout(T)[] collection, inout T elem) { // Blah, whatever} }{ // Blah, whatever }
Sep 07 2010
On 2010-09-07 14:49, Steven Schveighoffer wrote:On Sun, 05 Sep 2010 09:40:59 -0400, BLS <windevguy hotmail.de> wrote:inout is only used when you want to return the same constness (mutable, const, immutable) as you passed in to the function. If you don't want that, or don't want to return anything then const(T)[] is what you want. It will accept mutable, const and immutable. -- /Jacob CarlborgOn 05/09/2010 02:16, Jonathan M Davis wrote:inout void doesn't make any sense. You can't have a const void or immutable void. Now, if foo is a member function, then inout applies to the "this" pointer, but even then, you need a return type other than void for inout to be used. -Stevevoid foo(T)(T[] collection, T elem)I am curious, how this will look and feel once inout is working ? inout void foo(T)(inout(T)[] collection, inout T elem) { // Blah, whatever} }{ // Blah, whatever }
Sep 07 2010
On Tue, 07 Sep 2010 08:56:15 -0400, Jacob Carlborg <doob me.com> wrote:On 2010-09-07 14:49, Steven Schveighoffer wrote:Yes, exactly. This is why inout functions cannot return void. -SteveOn Sun, 05 Sep 2010 09:40:59 -0400, BLS <windevguy hotmail.de> wrote:inout is only used when you want to return the same constness (mutable, const, immutable) as you passed in to the function. If you don't want that, or don't want to return anything then const(T)[] is what you want. It will accept mutable, const and immutable.On 05/09/2010 02:16, Jonathan M Davis wrote:inout void doesn't make any sense. You can't have a const void or immutable void. Now, if foo is a member function, then inout applies to the "this" pointer, but even then, you need a return type other than void for inout to be used. -Stevevoid foo(T)(T[] collection, T elem)I am curious, how this will look and feel once inout is working ? inout void foo(T)(inout(T)[] collection, inout T elem) { // Blah, whatever} }{ // Blah, whatever }
Sep 07 2010
On 09/07/2010 03:15 PM, Steven Schveighoffer wrote:On Tue, 07 Sep 2010 08:56:15 -0400, Jacob Carlborg <doob me.com> wrote:Hmm. class C { void foo(void delegate(inout(C)) f) inout { f(this); } } Am I missing something?On 2010-09-07 14:49, Steven Schveighoffer wrote:Yes, exactly. This is why inout functions cannot return void. -SteveOn Sun, 05 Sep 2010 09:40:59 -0400, BLS <windevguy hotmail.de> wrote:inout is only used when you want to return the same constness (mutable, const, immutable) as you passed in to the function. If you don't want that, or don't want to return anything then const(T)[] is what you want. It will accept mutable, const and immutable.On 05/09/2010 02:16, Jonathan M Davis wrote:inout void doesn't make any sense. You can't have a const void or immutable void. Now, if foo is a member function, then inout applies to the "this" pointer, but even then, you need a return type other than void for inout to be used. -Stevevoid foo(T)(T[] collection, T elem)I am curious, how this will look and feel once inout is working ? inout void foo(T)(inout(T)[] collection, inout T elem) { // Blah, whatever} }{ // Blah, whatever }
Sep 07 2010
On Tue, 07 Sep 2010 09:28:18 -0400, Pelle <pelle.mansson gmail.com> wrote:On 09/07/2010 03:15 PM, Steven Schveighoffer wrote:Yes, a valid return. Your function should be: void foo(void delegate(const(C) f) const It helps to understand that inout/const/immutable has NOTHING to do with code generation, it only has to do with limiting what compiles. For this reason, an inout function is compiled once, and works on all three constancies (4 if you have a nested inout function). For the entire function any inout variable is treated as a non-changeable value, just like const. Then when you return, it's converted at the call site back to the constancy with which it was called. If the return value is void, then there's nothing to convert, and no reason to use inout over const. I'll repeat -- there is no benefit to inout if you are not returning anything. -SteveOn Tue, 07 Sep 2010 08:56:15 -0400, Jacob Carlborg <doob me.com> wrote:Hmm. class C { void foo(void delegate(inout(C)) f) inout { f(this); } } Am I missing something?On 2010-09-07 14:49, Steven Schveighoffer wrote:Yes, exactly. This is why inout functions cannot return void. -SteveOn Sun, 05 Sep 2010 09:40:59 -0400, BLS <windevguy hotmail.de> wrote:inout is only used when you want to return the same constness (mutable, const, immutable) as you passed in to the function. If you don't want that, or don't want to return anything then const(T)[] is what you want. It will accept mutable, const and immutable.On 05/09/2010 02:16, Jonathan M Davis wrote:inout void doesn't make any sense. You can't have a const void or immutable void. Now, if foo is a member function, then inout applies to the "this" pointer, but even then, you need a return type other than void for inout to be used. -Stevevoid foo(T)(T[] collection, T elem)I am curious, how this will look and feel once inout is working ? inout void foo(T)(inout(T)[] collection, inout T elem) { // Blah, whatever} }{ // Blah, whatever }
Sep 07 2010
On 09/07/2010 04:33 PM, Steven Schveighoffer wrote:Yes, a valid return. Your function should be: void foo(void delegate(const(C) f) const It helps to understand that inout/const/immutable has NOTHING to do with code generation, it only has to do with limiting what compiles. For this reason, an inout function is compiled once, and works on all three constancies (4 if you have a nested inout function). For the entire function any inout variable is treated as a non-changeable value, just like const. Then when you return, it's converted at the call site back to the constancy with which it was called. If the return value is void, then there's nothing to convert, and no reason to use inout over const. I'll repeat -- there is no benefit to inout if you are not returning anything. -SteveThat's not an equivalent function signature. Or maybe it is, but look at this (sorry it's so long): class C { int x; this(int y) { x = y; } inout(int*) foo() inout { return &x; } void bar(void delegate(int*) f) { f(&x); } void bar(void delegate(const(int*)) f) const { f(&x); } void bar(void delegate(immutable(int*)) f) immutable { f(&x); } } void main() { immutable(int)* wah; void wahwah(immutable(int*) x) { wah = x; } auto c = new immutable(C)(10); wahwah(c.foo); // why is this privilegied with inout c.bar(&wahwah); // and this not? writeln(*wah); } Can't use void delegate(const(int*)) there.
Sep 07 2010
On Tue, 07 Sep 2010 11:37:20 -0400, Pelle <pelle.mansson gmail.com> wrote:On 09/07/2010 04:33 PM, Steven Schveighoffer wrote:Thanks for clarifying, I didn't quite understand the usage before. This is a limitation of inout's design. Technically inout requires a single inout output, and can have multiple inout inputs. Your example matches that description, so in theory it's possible. But to simplify things, a function's only inout output must be on the return value. So things like void fn(inout int* x, out inout(int) y) don't qualify either. IMO there is a whole host of implicit delegate casting that should be possible, but isn't, including delegate contravariance. However, let's get inout working as it's currently designed before we go relaxing the requirements. I'm not a compiler/language designer, so I'm unsure if what you want has any pitfalls. -SteveYes, a valid return. Your function should be: void foo(void delegate(const(C) f) const It helps to understand that inout/const/immutable has NOTHING to do with code generation, it only has to do with limiting what compiles. For this reason, an inout function is compiled once, and works on all three constancies (4 if you have a nested inout function). For the entire function any inout variable is treated as a non-changeable value, just like const. Then when you return, it's converted at the call site back to the constancy with which it was called. If the return value is void, then there's nothing to convert, and no reason to use inout over const. I'll repeat -- there is no benefit to inout if you are not returning anything. -SteveThat's not an equivalent function signature. Or maybe it is, but look at this (sorry it's so long): class C { int x; this(int y) { x = y; } inout(int*) foo() inout { return &x; } void bar(void delegate(int*) f) { f(&x); } void bar(void delegate(const(int*)) f) const { f(&x); } void bar(void delegate(immutable(int*)) f) immutable { f(&x); } } void main() { immutable(int)* wah; void wahwah(immutable(int*) x) { wah = x; } auto c = new immutable(C)(10); wahwah(c.foo); // why is this privilegied with inout c.bar(&wahwah); // and this not? writeln(*wah); } Can't use void delegate(const(int*)) there.
Sep 07 2010
On Tue, 07 Sep 2010 14:06:58 -0400, Steven Schveighoffer <schveiguy yahoo.com> wrote:On Tue, 07 Sep 2010 11:37:20 -0400, Pelle <pelle.mansson gmail.com> wrote:I realized last night that this won't work. Simple reason -- during an inout function, the function promises to treat the arguments as if they were const. If your class instance was mutable, this would not be true, e.g.: class C { int x; void bar(void delegate(inout(int)* f) inout { f(&x); } } void main() { auto c = new C; void dg(int *f) {*f = 10;} c.bar(&dg); // modifies c, even though the function is marked as inout } -SteveOn 09/07/2010 04:33 PM, Steven Schveighoffer wrote:Thanks for clarifying, I didn't quite understand the usage before. This is a limitation of inout's design. Technically inout requires a single inout output, and can have multiple inout inputs. Your example matches that description, so in theory it's possible.Yes, a valid return. Your function should be: void foo(void delegate(const(C) f) const It helps to understand that inout/const/immutable has NOTHING to do with code generation, it only has to do with limiting what compiles. For this reason, an inout function is compiled once, and works on all three constancies (4 if you have a nested inout function). For the entire function any inout variable is treated as a non-changeable value, just like const. Then when you return, it's converted at the call site back to the constancy with which it was called. If the return value is void, then there's nothing to convert, and no reason to use inout over const. I'll repeat -- there is no benefit to inout if you are not returning anything. -SteveThat's not an equivalent function signature. Or maybe it is, but look at this (sorry it's so long): class C { int x; this(int y) { x = y; } inout(int*) foo() inout { return &x; } void bar(void delegate(int*) f) { f(&x); } void bar(void delegate(const(int*)) f) const { f(&x); } void bar(void delegate(immutable(int*)) f) immutable { f(&x); } } void main() { immutable(int)* wah; void wahwah(immutable(int*) x) { wah = x; } auto c = new immutable(C)(10); wahwah(c.foo); // why is this privilegied with inout c.bar(&wahwah); // and this not? writeln(*wah); } Can't use void delegate(const(int*)) there.
Sep 08 2010
On 09/08/2010 02:24 PM, Steven Schveighoffer wrote:On Tue, 07 Sep 2010 14:06:58 -0400, Steven Schveighoffer <schveiguy yahoo.com> wrote:Well, inout was conceived as a counter to where you need to write the exact same function for every type of constness, was it not? :-)On Tue, 07 Sep 2010 11:37:20 -0400, Pelle <pelle.mansson gmail.com> wrote:I realized last night that this won't work. Simple reason -- during an inout function, the function promises to treat the arguments as if they were const. If your class instance was mutable, this would not be true, e.g.: class C { int x; void bar(void delegate(inout(int)* f) inout { f(&x); } } void main() { auto c = new C; void dg(int *f) {*f = 10;} c.bar(&dg); // modifies c, even though the function is marked as inout } -SteveOn 09/07/2010 04:33 PM, Steven Schveighoffer wrote:Thanks for clarifying, I didn't quite understand the usage before. This is a limitation of inout's design. Technically inout requires a single inout output, and can have multiple inout inputs. Your example matches that description, so in theory it's possible.Yes, a valid return. Your function should be: void foo(void delegate(const(C) f) const It helps to understand that inout/const/immutable has NOTHING to do with code generation, it only has to do with limiting what compiles. For this reason, an inout function is compiled once, and works on all three constancies (4 if you have a nested inout function). For the entire function any inout variable is treated as a non-changeable value, just like const. Then when you return, it's converted at the call site back to the constancy with which it was called. If the return value is void, then there's nothing to convert, and no reason to use inout over const. I'll repeat -- there is no benefit to inout if you are not returning anything. -SteveThat's not an equivalent function signature. Or maybe it is, but look at this (sorry it's so long): class C { int x; this(int y) { x = y; } inout(int*) foo() inout { return &x; } void bar(void delegate(int*) f) { f(&x); } void bar(void delegate(const(int*)) f) const { f(&x); } void bar(void delegate(immutable(int*)) f) immutable { f(&x); } } void main() { immutable(int)* wah; void wahwah(immutable(int*) x) { wah = x; } auto c = new immutable(C)(10); wahwah(c.foo); // why is this privilegied with inout c.bar(&wahwah); // and this not? writeln(*wah); } Can't use void delegate(const(int*)) there.
Sep 08 2010
On Wed, 08 Sep 2010 12:38:44 -0400, Pelle <pelle.mansson gmail.com> wrote:On 09/08/2010 02:24 PM, Steven Schveighoffer wrote:Not exactly, it was conceived as a solution for the case where you would normally write a const function, but you don't want it to alter your const contract with the object in question. Basically, you want a function that promises not to alter the parameters, but gives you back one of your parameters or a portion of one of them in the same constancy you pass in. The classic example is a property getter. If you are not returning a portion of the input, then you can use const instead. -SteveOn Tue, 07 Sep 2010 14:06:58 -0400, Steven Schveighoffer <schveiguy yahoo.com> wrote:Well, inout was conceived as a counter to where you need to write the exact same function for every type of constness, was it not? :-)On Tue, 07 Sep 2010 11:37:20 -0400, Pelle <pelle.mansson gmail.com> wrote:I realized last night that this won't work. Simple reason -- during an inout function, the function promises to treat the arguments as if they were const. If your class instance was mutable, this would not be true, e.g.: class C { int x; void bar(void delegate(inout(int)* f) inout { f(&x); } } void main() { auto c = new C; void dg(int *f) {*f = 10;} c.bar(&dg); // modifies c, even though the function is marked as inout } -SteveOn 09/07/2010 04:33 PM, Steven Schveighoffer wrote:Thanks for clarifying, I didn't quite understand the usage before. This is a limitation of inout's design. Technically inout requires a single inout output, and can have multiple inout inputs. Your example matches that description, so in theory it's possible.Yes, a valid return. Your function should be: void foo(void delegate(const(C) f) const It helps to understand that inout/const/immutable has NOTHING to do with code generation, it only has to do with limiting what compiles. For this reason, an inout function is compiled once, and works on all three constancies (4 if you have a nested inout function). For the entire function any inout variable is treated as a non-changeable value, just like const. Then when you return, it's converted at the call site back to the constancy with which it was called. If the return value is void, then there's nothing to convert, and no reason to use inout over const. I'll repeat -- there is no benefit to inout if you are not returning anything. -SteveThat's not an equivalent function signature. Or maybe it is, but look at this (sorry it's so long): class C { int x; this(int y) { x = y; } inout(int*) foo() inout { return &x; } void bar(void delegate(int*) f) { f(&x); } void bar(void delegate(const(int*)) f) const { f(&x); } void bar(void delegate(immutable(int*)) f) immutable { f(&x); } } void main() { immutable(int)* wah; void wahwah(immutable(int*) x) { wah = x; } auto c = new immutable(C)(10); wahwah(c.foo); // why is this privilegied with inout c.bar(&wahwah); // and this not? writeln(*wah); } Can't use void delegate(const(int*)) there.
Sep 08 2010
On 2010-09-07 17:37, Pelle wrote:On 09/07/2010 04:33 PM, Steven Schveighoffer wrote:That won't work, you can't have inout on return of a function without having inout for a least one parameter. The compiler can't know what to resolve inout to, mutable, immutable or const. -- /Jacob CarlborgYes, a valid return. Your function should be: void foo(void delegate(const(C) f) const It helps to understand that inout/const/immutable has NOTHING to do with code generation, it only has to do with limiting what compiles. For this reason, an inout function is compiled once, and works on all three constancies (4 if you have a nested inout function). For the entire function any inout variable is treated as a non-changeable value, just like const. Then when you return, it's converted at the call site back to the constancy with which it was called. If the return value is void, then there's nothing to convert, and no reason to use inout over const. I'll repeat -- there is no benefit to inout if you are not returning anything. -SteveThat's not an equivalent function signature. Or maybe it is, but look at this (sorry it's so long): class C { int x; this(int y) { x = y; } inout(int*) foo() inout { return &x; } void bar(void delegate(int*) f) { f(&x); } void bar(void delegate(const(int*)) f) const { f(&x); } void bar(void delegate(immutable(int*)) f) immutable { f(&x); } } void main() { immutable(int)* wah; void wahwah(immutable(int*) x) { wah = x; } auto c = new immutable(C)(10); wahwah(c.foo); // why is this privilegied with inout c.bar(&wahwah); // and this not? writeln(*wah); } Can't use void delegate(const(int*)) there.
Sep 07 2010