digitalmars.D - Is alias equality inconsistent?
- Jens Mueller (18/18) May 13 2011 Hi,
- Timon Gehr (8/26) May 13 2011 Hi,
- Jonathan M Davis (6/41) May 13 2011 Except that static arrays and dynamic arrays are different beasts and sh...
- Timon Gehr (17/62) May 13 2011 If that is true to the extent implied by you, then D is doing it all wro...
- Jonathan M Davis (11/79) May 13 2011 They are different because dynamic arrays are reference types and static...
- Timon Gehr (14/47) May 13 2011 I understand that. But that does not mean they should be treated differe...
- Andrei Alexandrescu (6/11) May 13 2011 I think 'is' for static arrays could go either way. If they're to be
- Timon Gehr (11/22) May 13 2011 I think determining the return value should rely on other things than th...
- Jonathan M Davis (7/40) May 13 2011 The only value of is and static arrays that I can think of is if you can...
- Timon Gehr (1/8) May 13 2011 is on static arrays compares ptr and length too. So it is different from...
- Jonathan M Davis (13/24) May 13 2011 And of what value is that? == should already doing that before checking ...
- Timon Gehr (49/73) May 14 2011 Ah, thats what you are referring to. Yes, 'is' on two static arrays can ...
- Timon Gehr (3/5) May 14 2011 Just realized that changing it would imply there would be no way to chec...
Hi, I find that comparing for alias equality is a bit odd. Maybe somebody can shed some light into it. int a = 1; int b = 1; assert(a is b); but int[1] aFixedArray = [1]; int[1] bFixedArray = [1]; assert(aFixedArray !is bFixedArray); It behaves as specified in TDPL p. 57: "If a and b are arrays or class references, the result is true if and only if a and b are two names for the same actual object; Otherwise, a is b is the same as a == b." But fixed-size arrays have value semantics as int, float etc. So why is alias equality not consistent with value vs. reference semantics? Why this exception for fixed-size arrays? Jens
May 13 2011
Hi, I find that comparing for alias equality is a bit odd. Maybe somebody can shed some light into it. int a = 1; int b = 1; assert(a is b); but int[1] aFixedArray = [1]; int[1] bFixedArray = [1]; assert(aFixedArray !is bFixedArray); It behaves as specified in TDPL p. 57: "If a and b are arrays or class references, the result is true if and only if a and b are two names for the same actual object; Otherwise, a is b is the same as a == b." But fixed-size arrays have value semantics as int, float etc. So why is alias equality not consistent with value vs. reference semantics? Why this exception for fixed-size arrays? JensHi, I think it is more consistent this way, because static arrays are closer to dynamic arrays than to int, float etc. If you write generic code, it is more likely that the template will be instantiated with for example both of int[6] and int[] than int[6] and float for the same parameter. You really want the semantics of 'is' to be consistent between different array types. Timon
May 13 2011
On 2011-05-13 12:30, Timon Gehr wrote:Except that static arrays and dynamic arrays are different beasts and should _not_ be treated the same. A dynamic array which references a static array should be treated the same as another dynamic array, but static arrays and dynamic arrays should _not_ be treated the same. They're very different. - Jonathan M DavisHi, I find that comparing for alias equality is a bit odd. Maybe somebody can shed some light into it. int a = 1; int b = 1; assert(a is b); but int[1] aFixedArray = [1]; int[1] bFixedArray = [1]; assert(aFixedArray !is bFixedArray); It behaves as specified in TDPL p. 57: "If a and b are arrays or class references, the result is true if and only if a and b are two names for the same actual object; Otherwise, a is b is the same as a == b." But fixed-size arrays have value semantics as int, float etc. So why is alias equality not consistent with value vs. reference semantics? Why this exception for fixed-size arrays? JensHi, I think it is more consistent this way, because static arrays are closer to dynamic arrays than to int, float etc. If you write generic code, it is more likely that the template will be instantiated with for example both of int[6] and int[] than int[6] and float for the same parameter. You really want the semantics of 'is' to be consistent between different array types.
May 13 2011
Jonathan M Davis wrote:On 2011-05-13 12:30, Timon Gehr wrote:If that is true to the extent implied by you, then D is doing it all wrong anyway: declaration: int[] arr; vs int[N] arr; extract value: arr[x] vs arr[x] store value: arr[x] = v; vs arr[x] = v; slice: arr[a..b] vs arr[a..b] get pointer: arr.ptr vs arr.ptr get length: arr.length vs arr.length ... (you see where this is going) Jonathan M Davis wrote:Except that static arrays and dynamic arrays are different beasts and should _not_ be treated the same. A dynamic array which references a static array should be treated the same as another dynamic array, but static arrays and dynamic arrays should _not_ be treated the same. They're very different. - Jonathan M DavisHi, I find that comparing for alias equality is a bit odd. Maybe somebody can shed some light into it. int a = 1; int b = 1; assert(a is b); but int[1] aFixedArray = [1]; int[1] bFixedArray = [1]; assert(aFixedArray !is bFixedArray); It behaves as specified in TDPL p. 57: "If a and b are arrays or class references, the result is true if and only if a and b are two names for the same actual object; Otherwise, a is b is the same as a == b." But fixed-size arrays have value semantics as int, float etc. So why is alias equality not consistent with value vs. reference semantics? Why this exception for fixed-size arrays? JensHi, I think it is more consistent this way, because static arrays are closer to dynamic arrays than to int, float etc. If you write generic code, it is more likely that the template will be instantiated with for example both of int[6] and int[] than int[6] and float for the same parameter. You really want the semantics of 'is' to be consistent between different array types.I'm surprised that is works with value semantics at all. I would have expected that to be a compiler error. Barring that, I would have expected it to be false for value types unless a variable was compared with itself with is. This definitely seems off.Not at all. What you suggest is that 'is' should compare the addresses of its arguments. It is not at all like that. For classes 'is' compares its actual arguments while == has an additional indirection. You can think of value types as references to unique immutable data. They behave just the same, except that they are more efficient. I think 'is' works just as it is supposed to. Timon
May 13 2011
Jonathan M Davis wrote:They are different because dynamic arrays are reference types and static arrays are value types. That has a definite impact when copying and assigning them. It has an impact on anything which differs depending on value and reference semantics. That can have far-reaching impacts.On 2011-05-13 12:30, Timon Gehr wrote:If that is true to the extent implied by you, then D is doing it all wrong anyway: declaration: int[] arr; vs int[N] arr; extract value: arr[x] vs arr[x] store value: arr[x] = v; vs arr[x] = v; slice: arr[a..b] vs arr[a..b] get pointer: arr.ptr vs arr.ptr get length: arr.length vs arr.length ... (you see where this is going)Except that static arrays and dynamic arrays are different beasts and should _not_ be treated the same. A dynamic array which references a static array should be treated the same as another dynamic array, but static arrays and dynamic arrays should _not_ be treated the same. They're very different. - Jonathan M DavisHi, I find that comparing for alias equality is a bit odd. Maybe somebody can shed some light into it. int a = 1; int b = 1; assert(a is b); but int[1] aFixedArray = [1]; int[1] bFixedArray = [1]; assert(aFixedArray !is bFixedArray); It behaves as specified in TDPL p. 57: "If a and b are arrays or class references, the result is true if and only if a and b are two names for the same actual object; Otherwise, a is b is the same as a == b." But fixed-size arrays have value semantics as int, float etc. So why is alias equality not consistent with value vs. reference semantics? Why this exception for fixed-size arrays? JensHi, I think it is more consistent this way, because static arrays are closer to dynamic arrays than to int, float etc. If you write generic code, it is more likely that the template will be instantiated with for example both of int[6] and int[] than int[6] and float for the same parameter. You really want the semantics of 'is' to be consistent between different array types.Jonathan M Davis wrote:It was my understanding that is was specifically intended for comparing reference equality. As such, it has no business being used to compare value types. If, on the other hand, it is merely doing a comparison with no indirections, then is and == would be the same for value types and would make sense. I'm not sure what was actually intended by Walter. I am, however, very surprised to see is work with value types. - Jonathan M DavisI'm surprised that is works with value semantics at all. I would have expected that to be a compiler error. Barring that, I would have expected it to be false for value types unless a variable was compared with itself with is. This definitely seems off.Not at all. What you suggest is that 'is' should compare the addresses of its arguments. It is not at all like that. For classes 'is' compares its actual arguments while == has an additional indirection. You can think of value types as references to unique immutable data. They behave just the same, except that they are more efficient. I think 'is' works just as it is supposed to.
May 13 2011
Jonathan M Davis wrote:I understand that. But that does not mean they should be treated differently where they can be treated uniformly. What I am claiming is that 'is' is a feature on the same level as the primitives listed above.If that is true to the extent implied by you, then D is doing it all wrong anyway: declaration: int[] arr; vs int[N] arr; extract value: arr[x] vs arr[x] store value: arr[x] = v; vs arr[x] = v; slice: arr[a..b] vs arr[a..b] get pointer: arr.ptr vs arr.ptr get length: arr.length vs arr.length ... (you see where this is going)They are different because dynamic arrays are reference types and static arrays are value types. That has a definite impact when copying and assigning them. It has an impact on anything which differs depending on value and reference semantics. That can have far-reaching impacts.As its in TDPL and DMD I think that is pretty much what Walter intended. 'is' is only there because there is no other (safe/convenient) means of testing for shallow equality in D. Fixed-size arrays are somewhat special, there 'is' actually compares ptr and length. I think that is very practical and makes sense because it allows meaningful 'is' between fixed- and dynamic-size arrays. I guess for value types it is there for completeness and maybe to enable easier generic programming. We do not lose anything by having it. TimonJonathan M Davis wrote:It was my understanding that is was specifically intended for comparing reference equality. As such, it has no business being used to compare value types. If, on the other hand, it is merely doing a comparison with no indirections, then is and == would be the same for value types and would make sense. I'm not sure what was actually intended by Walter. I am, however, very surprised to see is work with value types. - Jonathan M DavisI'm surprised that is works with value semantics at all. I would have expected that to be a compiler error. Barring that, I would have expected it to be false for value types unless a variable was compared with itself with is. This definitely seems off.Not at all. What you suggest is that 'is' should compare the addresses of its arguments. It is not at all like that. For classes 'is' compares its actual arguments while == has an additional indirection. You can think of value types as references to unique immutable data. They behave just the same, except that they are more efficient. I think 'is' works just as it is supposed to.
May 13 2011
On 5/13/11 5:00 PM, Timon Gehr wrote:Fixed-size arrays are somewhat special, there 'is' actually compares ptr and length. I think that is very practical and makes sense because it allows meaningful 'is' between fixed- and dynamic-size arrays. I guess for value types it is there for completeness and maybe to enable easier generic programming. We do not lose anything by having it.I think 'is' for static arrays could go either way. If they're to be seen as an equivalent of structs, is should yield true. If they're to be seen as a close relative of dynamic arrays, is should yield false. Probably it would be best to disable it :o). Andrei
May 13 2011
On 5/13/11 5:00 PM, Timon Gehr wrote:I think determining the return value should rely on other things than the ref-ness of the arguments. Maybe you want to clarify. When you are disabling stuff, also disable templates and all builtin types. Using the mixin/asm statements they can be implemented entirely in library code. I will then start patching my compiler. I am serious about that one. =) When did it stop being useful? I thought D should be a practical language that gets you stuff done, not a religion. Now it seems to me that you want to disable 'is' for static arrays just because there would be another (less useful) way to define it? Or is the ':o)' an indication that you were just joking? It would be a relief. TimonFixed-size arrays are somewhat special, there 'is' actually compares ptr and length. I think that is very practical and makes sense because it allows meaningful 'is' between fixed- and dynamic-size arrays. I guess for value types it is there for completeness and maybe to enable easier generic programming. We do not lose anything by having it.I think 'is' for static arrays could go either way. If they're to be seen as an equivalent of structs, is should yield true. If they're to be seen as a close relative of dynamic arrays, is should yield false. Probably it would be best to disable it :o). Andrei
May 13 2011
The only value of is and static arrays that I can think of is if you can use them to verify whether a dynamic array refers to a particular static array. Other than that, what value do they add? If you're checking for equality, then use ==. That one use case may make it useful to allow for is in comparing static and dynamic arrays, but other than that, I don't really see what is gives you when comparing static arrays. - Jonathan M DavisOn 5/13/11 5:00 PM, Timon Gehr wrote:I think determining the return value should rely on other things than the ref-ness of the arguments. Maybe you want to clarify. When you are disabling stuff, also disable templates and all builtin types. Using the mixin/asm statements they can be implemented entirely in library code. I will then start patching my compiler. I am serious about that one. =) When did it stop being useful? I thought D should be a practical language that gets you stuff done, not a religion. Now it seems to me that you want to disable 'is' for static arrays just because there would be another (less useful) way to define it? Or is the ':o)' an indication that you were just joking? It would be a relief.Fixed-size arrays are somewhat special, there 'is' actually compares ptr and length. I think that is very practical and makes sense because it allows meaningful 'is' between fixed- and dynamic-size arrays. I guess for value types it is there for completeness and maybe to enable easier generic programming. We do not lose anything by having it.I think 'is' for static arrays could go either way. If they're to be seen as an equivalent of structs, is should yield true. If they're to be seen as a close relative of dynamic arrays, is should yield false. Probably it would be best to disable it :o). Andrei
May 13 2011
The only value of is and static arrays that I can think of is if you can use them to verify whether a dynamic array refers to a particular static array. Other than that, what value do they add? If you're checking for equality, then use ==. That one use case may make it useful to allow for is in comparing static and dynamic arrays, but other than that, I don't really see what is gives you when comparing static arrays. - Jonathan M Davisis on static arrays compares ptr and length too. So it is different from ==.
May 13 2011
On 2011-05-13 17:28, Timon Gehr wrote:And of what value is that? == should already doing that before checking for equality on each of the elements, because if the ptr and length are identical, then there's no point checking the elements for equality. So, is doesn't add any benefit there, unless == is poorly implemented for static arrays. Static arrays are value types, not reference types, so checking whether two of them refer to the same array makes no sense. Checking whether a dynamic array refers to a static array makes sense, but checking whether two static arrays are the same array does not. And since == should shortcut when comparing a static array to itself (heck, the compiler should be able to optimize the check out entirely and replace it with true), I don't see how using is on two static arrays does anything for you at all. - Jonathan M DavisThe only value of is and static arrays that I can think of is if you can use them to verify whether a dynamic array refers to a particular static array. Other than that, what value do they add? If you're checking for equality, then use ==. That one use case may make it useful to allow for is in comparing static and dynamic arrays, but other than that, I don't really see what is gives you when comparing static arrays. - Jonathan M Davisis on static arrays compares ptr and length too. So it is different from ==.
May 13 2011
On 2011-05-13 17:28, Timon Gehr wrote:== currently checks length but not ptr for both static and dynamic arrays.And of what value is that? == should already doing that before checking for equality on each of the elements, because if the ptr and length are identical, then there's no point checking the elements for equality. So, is doesn't add any benefit there, unless == is poorly implemented for static arrays.The only value of is and static arrays that I can think of is if you can use them to verify whether a dynamic array refers to a particular static array. Other than that, what value do they add? If you're checking for equality, then use ==. That one use case may make it useful to allow for is in comparing static and dynamic arrays, but other than that, I don't really see what is gives you when comparing static arrays. - Jonathan M Davisis on static arrays compares ptr and length too. So it is different from ==.Static arrays are value types, not reference types, so checking whether two of them refer to the same array makes no sense. Checking whether a dynamic array refers to a static array makes sense, but checking whether two static arrays are the same array does not. And since == should shortcut when comparing a static array to itself (heck, the compiler should be able to optimize the check out entirely and replace it with true), I don't see how using is on two static arrays does anything for you at all. - Jonathan M DavisAh, thats what you are referring to. Yes, 'is' on two static arrays can be resolved entirely on compile time. And disallowing 'is' for static arrays is actually one check more in the compiler, so the compiler gets slightly more complicated. This works against D's goals ;). Apart from that, saying that dynamic arrays are reference types and ergo 'is' makes sense is somewhat incomplete, because they are actually value types (structs) with some reference-like behavior: //does not change its argument void foo(int[] a){ a.length=3*a.length; a[0]=10029; } //this does (but it cannot take a static array) void foo(ref int[] a){ a.length=3*a.length; a[0]=10029; } It is not beautiful but practical... Same goes for some reference-like behavior of static arrays. You can think of static arrays as being the same as dynamic arrays except that they define a postblit operator and cannot be resized. You can also think of them as being structs that embed all the data and define opBinary("is"). The current semantics of static arrays allow both interpretations if you do not want to get too low level. What about static array references by the way? With ref arguments static and dynamic arrays even have similar semantics (except that you cannot change the length of a static array). But ref arguments are a different beast. 'is' does not work as may be expected by some: bool bar(ref int a, ref int b){ return a is b; } void main(){ int x=0,y=1; assert(!bar(x,y)); x=1; assert(bar(x,y)); } Again, if you understand that value types are similar to immutable references, it makes sense. But I think that this behavior could as well be changed. Besides: consider a little analogy: if(x==y){..} //fine. if(x==1){..} //fine. if(2==y){..} //fine. if(2==1){..} //there for completeness Just because you do not want to write 2==1 so often, do you want to remove it from the language? And then you would remove x==1 and 2==y too? I think what D is doing now feels right and consistent. Timon
May 14 2011
Again, if you understand that value types are similar to immutable references, it makes sense. But I think that this behavior could as well be changed.Just realized that changing it would imply there would be no way to check for alias equality of two class reference references. It should remain as it is. Timon
May 14 2011