Lars Fosdal 1792 Posted February 18, 2019 Not all for loops are created equal.Considerfor x in [value1, value2, value3]You would expect to see x vary in the order of the values in the list. However – if x and the values are of an enumerated type, looping the “list” does NOT loop in the apparent order of the constant, but in the order of the enumerated type declaration, such as it would for any set. Example at: https://larsfosdal.blog/2019/02/18/delphi-pitfalls-enumerated-types-and-for-loops/ Share this post Link to post
Attila Kovacs 629 Posted February 18, 2019 (edited) That's what I was referring to in your previous post https://stackoverflow.com/questions/4950129/delphi-for-in-loop-set-enumeration-order and https://stackoverflow.com/questions/1600575/iterate-through-items-in-an-enumeration-in-delphi Edited February 18, 2019 by Attila Kovacs 1 Share this post Link to post
Stefan Glienke 2002 Posted February 18, 2019 2 hours ago, Lars Fosdal said: You would expect to see x vary in the order of the values in the list. No I would not because its not a list but a set which are implemented as bitmask and thus have a fixed order. 4 1 Share this post Link to post
Lars Fosdal 1792 Posted February 18, 2019 28 minutes ago, Stefan Glienke said: No I would not because its not a list but a set which are implemented as bitmask and thus have a fixed order. It is pretty quick to miss that "detail". They look the same, so unless you really pay attention to the type element type - there is little to tell you that you are looking at a set and not a list. Share this post Link to post
Stefan Glienke 2002 Posted February 18, 2019 Strictly speaking assuming a specific order in a for-in loop is wrong to begin with. 4 Share this post Link to post
Lars Fosdal 1792 Posted February 18, 2019 2 minutes ago, Stefan Glienke said: Strictly speaking assuming a specific order in a for-in loop is wrong to begin with. For a list or any other object enumeration interface, I'd agree - but for an open array or a TArray? Share this post Link to post
Stefan Glienke 2002 Posted February 18, 2019 Just now, Lars Fosdal said: For a list or any other object enumeration interface, I'd agree - but for an open array or a TArray? I could answer that by quoting your previous comment 😉 Share this post Link to post
Lars Fosdal 1792 Posted February 18, 2019 7 minutes ago, Stefan Glienke said: I could answer that by quoting your previous comment 😉 Except it is rare to see a TList or any other object structure "hardcoded" in plain sight, while arrays of simple types are not hard to read nor uncommon. Share this post Link to post
Stefan Glienke 2002 Posted February 18, 2019 (edited) AFAIK you cannot inline declare an array in a for in loop so having some elements in between square brackets will always be a set. You can see it in your very own code on your blog article where you had to put them into an array variable first to then process them in the loop. The point I agree with though is that the fact that sets and arrays share its syntax might be confusing sometimes. Edited February 18, 2019 by Stefan Glienke 1 Share this post Link to post
Uwe Raabe 2057 Posted February 18, 2019 13 minutes ago, Lars Fosdal said: For a list or any other object enumeration interface, I'd agree - but for an open array or a TArray? A for-in-loop doesn't guarantee some order. Any order seen just relies on the implementation and may be subject to change in the future. (Latest when we compile for quantum computers) I remember someone asking for a backwards for-in-loop, but that request is based on a false assumption in the first place. Share this post Link to post
Lars Fosdal 1792 Posted February 18, 2019 I wonder how it behaves if I have a set enumerated type with hard coded ordinal values? Edit Change the declaration to TEnum = (plough = 5, foo = 9, bar = 14, wtf = 1); Now the set behaves just like the array. Share this post Link to post
Lars Fosdal 1792 Posted February 18, 2019 @Uwe Raabe Are you saying that for ix := Low(Array) to High(Array) do begin v := Array[ix]; is predictable - while for v in Array is not predictable ? Share this post Link to post
Lars Fosdal 1792 Posted February 18, 2019 Off-topic - I actually do reverse for in loops with a custom enumerator which starts on top and decrements instead. Share this post Link to post
Stefan Glienke 2002 Posted February 18, 2019 That is why I wrote "strictly speaking" because there is always a difference between a formal language or syntax specification and its implementation based on its actual type. Currently probably every language that has some kind of for-in or foreach loop of course operates an array in order but that does not mean that you can assume this for every type operable with such loops. And when we are talking about "just for arrays" this is what is called "implementation detail". Share this post Link to post
Lars Fosdal 1792 Posted February 18, 2019 The inconsistent behavior between the two variations of enumerated types is another pitfall, I guess. Share this post Link to post
Stefan Glienke 2002 Posted February 18, 2019 1 minute ago, Lars Fosdal said: Or pitfall 😛 Confusing sets with arrays because they look similar is the pitfall 15 minutes ago, Lars Fosdal said: Edit Change the declaration to TEnum = (plough = 5, foo = 9, bar = 14, wtf = 1); Now the set behaves just like the array. It does not, bar and foo are still reversed 😉 Share this post Link to post
Lars Fosdal 1792 Posted February 18, 2019 1 minute ago, Stefan Glienke said: It does not, bar and foo are still reversed 😉 1 Wow, I didn't notice that! And it is not related to declaration order, nor ordinal value. That is a bit disturbing. Share this post Link to post
Stefan Glienke 2002 Posted February 18, 2019 Just now, Lars Fosdal said: Wow, I didn't notice that! And it is not related to declaration order, nor ordinal value. That is a bit disturbing. You should take a break - because it in fact is related to the ordinal value. The order is wtf, plough, foo, bar - but your array was wtf, plough, bar, foo Share this post Link to post
Lars Fosdal 1792 Posted February 18, 2019 2 minutes ago, Stefan Glienke said: You should take a break - because it in fact is related to the ordinal value. The order is wtf, plough, foo, bar - but your array was wtf, plough, bar, foo Declared: TEnum = (plough, foo, bar, wtf) Test order: [wtf, plough, bar, foo] Looping an Enum Set 1 wtf 5 plough 9 foo 14 bar Looping an Enum Array 1 wtf 5 plough 14 bar 9 foo Press Enter: You are right, @Stefan Glienke -I am so logging off now 😄 2 Share this post Link to post
Lars Fosdal 1792 Posted February 20, 2019 (edited) Off-topic: There is another oddity with enumerations with explicit ordinal values. TEnum = (plough = 5, foo = 9, bar = 14, wtf = 1000); The above is valid, but wtf can't be used in a set. Makes me wonder if it would be better to generally do sets as dynamic arrays, instead of today's implementation of sets. I guess it would be more expensive. Edited February 21, 2019 by Lars Fosdal Corrected open array to dynamic array. Share this post Link to post
Stefan Glienke 2002 Posted February 20, 2019 (edited) When used in a set, the ordinal value of the enum is basically the index of the bit used within the set and as they can only be 256 bit in size any ordinal value above 255 prevents an enum being used as a set. Personally I think you should rather avoid giving enums any ordinal values and only ever use them when using some interop with another system where they are used for. Edited February 20, 2019 by Stefan Glienke 1 Share this post Link to post
Rudy Velthuis 91 Posted February 20, 2019 10 hours ago, Lars Fosdal said: Makes me wonder if it would be better to generally do sets as open arrays, instead of today's implementation of sets. What do you mean with "open arrays"? The only open arrays I know are open array parameters and I have no idea how you would implement sets with them. Did you perhaps mean dynamic arrays? If so, then please don't use confusing terminology. And it really gets confusing and troublesome if you confuse such "open arrays" with open array parameters. FWIW, there is already a TBits class, implementing an indexed bitset. Share this post Link to post
Lars Fosdal 1792 Posted February 21, 2019 I did mean dynamic arrays. My bad. Share this post Link to post
Lars Fosdal 1792 Posted February 21, 2019 19 hours ago, Stefan Glienke said: When used in a set, the ordinal value of the enum is basically the index of the bit used within the set and as they can only be 256 bit in size any ordinal value above 255 prevents an enum being used as a set. Personally I think you should rather avoid giving enums any ordinal values and only ever use them when using some interop with another system where they are used for. Isn't there something weird about RTTI for enums that have manually set ordinal values as well? Share this post Link to post