digitalmars.D - Switch: Case Range Syntax
- Vijay Nayar (23/23) Aug 17 2011 D adds a very handy feature that allows you to check for a range of
- Lars T. Kyllingstad (20/24) Aug 17 2011 This was discussed when the feature was introduced back in 2009. See
- Vijay Nayar (5/35) Aug 17 2011 Thanks for the post! This kind of history is pretty fascinating and I'l...
- bearophile (5/8) Aug 17 2011 The current syntax is a compromise of several different needs, and it's ...
- Jonathan M Davis (11/36) Aug 17 2011 I don't know, but ranged case statements don't have the same semantics a...
- Jacob Carlborg (11/47) Aug 17 2011 D should have a built-in range type. One that supports syntax for both
- simendsjo (4/58) Aug 17 2011 int a = 3 .. 5;
- Marco Leise (10/73) Aug 18 2011 Delphi uses ranges in a way similar to declaring an enum:
-
Robert Clipsham
(6/15)
Aug 17 2011
- Timon Gehr (7/61) Aug 17 2011 The .. 'operator' is the operator with the lowest precedence in D (it
- Jacob Carlborg (6/24) Aug 18 2011 I don't see either how this could be changed without a breaking language...
- Jonathan M Davis (10/64) Aug 17 2011 I suggest that you read the thread that Lars linked to. That type of syn...
- Jacob Carlborg (6/70) Aug 18 2011 Yes I know that it has been discussed before. We don't have to discuss
- Jacob Carlborg (5/14) Aug 18 2011 BTW, I think it would be more useful to have a built-in type for ranges
- bearophile (6/18) Aug 17 2011 Regarding just switches, GCC has a non standard syntax extension that al...
- Vijay Nayar (9/38) Aug 17 2011 That's pretty clever. They recognized the ambiguity problem of
- Andrei Alexandrescu (16/70) Aug 17 2011 I doubt that would work well. Let's ignore for now mundane issues such
- Jacob Carlborg (11/37) Aug 18 2011 I'm just hoping that floating point syntax will be removed. I know a lot...
- Andrei Alexandrescu (8/48) Aug 18 2011 There could be indeed a lot of things. My point is that there _need_ to
- Jacob Carlborg (9/62) Aug 18 2011 Ok, we can stop this discussion. In my original post I was just trying
- Vijay Nayar (16/38) Aug 18 2011 From this discussion, I gather that the 'switch' statement is effectivel...
- Andrei Alexandrescu (7/45) Aug 18 2011 The exact behavior is dependent on the compiler implementation.
- Don (5/46) Aug 18 2011 Yes. That's why the maximum length of the range is currently limited to
- Timon Gehr (10/33) Aug 17 2011 With the other syntax, the wrapping switch statement really should look
D adds a very handy feature that allows you to check for a range of values in a single case. Is there a particular reason that the syntax "case <start>: .. case <end>:" is used instead of treating the case statement similarly to an array slice, e.g. "case <start> .. <end>:"? For example: import std.stdio; void main() { int bob = 12; switch (bob) { // Why not "case 0 .. 9:"? case 0: .. case 9: writeln("Less than 10."); case 10: .. case 19: writeln("Less than 20."); case 20: .. case 29: writeln("Less than 30."); break; default: break; } // Output: Less than 20. Less than 30. } - Vijay
Aug 17 2011
On Wed, 17 Aug 2011 17:27:43 +0000, Vijay Nayar wrote:D adds a very handy feature that allows you to check for a range of values in a single case. Is there a particular reason that the syntax "case <start>: .. case <end>:" is used instead of treating the case statement similarly to an array slice, e.g. "case <start> .. <end>:"?This was discussed when the feature was introduced back in 2009. See this thread for details: http://www.digitalmars.com/d/archives/digitalmars/D/ Case_Range_Statement_.._92818.html Personally, I think case range statements make more sense (and look better) when they are typed like this: switch (someNumber) { case 0: .. case 9: writeln("Less than 10"); break; case 10: .. case 19: // and so on } -Lars
Aug 17 2011
On Wed, 17 Aug 2011 17:40:40 +0000, Lars T. Kyllingstad wrote:On Wed, 17 Aug 2011 17:27:43 +0000, Vijay Nayar wrote:Thanks for the post! This kind of history is pretty fascinating and I'll give it a good read. From what I've read so far, I'm surprised at how heated the debate becomes :) - VijayD adds a very handy feature that allows you to check for a range of values in a single case. Is there a particular reason that the syntax "case <start>: .. case <end>:" is used instead of treating the case statement similarly to an array slice, e.g. "case <start> .. <end>:"?This was discussed when the feature was introduced back in 2009. See this thread for details: http://www.digitalmars.com/d/archives/digitalmars/D/ Case_Range_Statement_.._92818.html Personally, I think case range statements make more sense (and look better) when they are typed like this: switch (someNumber) { case 0: .. case 9: writeln("Less than 10"); break; case 10: .. case 19: // and so on } -Lars
Aug 17 2011
Vijay Nayar:Thanks for the post! This kind of history is pretty fascinating and I'll give it a good read. From what I've read so far, I'm surprised at how heated the debate becomes :)The current syntax is a compromise of several different needs, and it's acceptable, despite a minor fault (it reminds a bit too much the slice syntax, despite including the final item. The final item is included because it is more handy for char ranges: you are allowed to write case 'a': .. case 'z': to take all lowercase ASCII). I'd like some support for final switches on integers, and to use range case syntax in final switches too. Bye, bearophile
Aug 17 2011
On Wednesday, August 17, 2011 10:27 Vijay Nayar wrote:D adds a very handy feature that allows you to check for a range of values in a single case. Is there a particular reason that the syntax "case <start>: .. case <end>:" is used instead of treating the case statement similarly to an array slice, e.g. "case <start> .. <end>:"? For example: import std.stdio; void main() { int bob = 12; switch (bob) { // Why not "case 0 .. 9:"? case 0: .. case 9: writeln("Less than 10."); case 10: .. case 19: writeln("Less than 20."); case 20: .. case 29: writeln("Less than 30."); break; default: break; } // Output: Less than 20. Less than 30. }I don't know, but ranged case statements don't have the same semantics as giving a range of values when slicing or to a foreach loop, so that may be why. arr[0 .. 10] does _not_ include the element at index 10. case 0: case 10: _does_ include 10. So, it actually probably be a bad thing for them to use the same syntax. To use the same syntax for both would make the semantics of that syntax inconsistent and confusing. - Jonathan M Davis
Aug 17 2011
On 2011-08-17 19:48, Jonathan M Davis wrote:On Wednesday, August 17, 2011 10:27 Vijay Nayar wrote:D should have a built-in range type. One that supports syntax for both including and excluding the last element: auto a = 3 .. 5 auto b = 3 ... 5 Then we wouldn't need a special range syntax for switch statements. You could store ranges in variables and pass them to functions. opSlice probably wouldn't be needed, instead opIndex could be used and you would declare the method to take a range instead of two integers. -- /Jacob CarlborgD adds a very handy feature that allows you to check for a range of values in a single case. Is there a particular reason that the syntax "case<start>: .. case<end>:" is used instead of treating the case statement similarly to an array slice, e.g. "case<start> ..<end>:"? For example: import std.stdio; void main() { int bob = 12; switch (bob) { // Why not "case 0 .. 9:"? case 0: .. case 9: writeln("Less than 10."); case 10: .. case 19: writeln("Less than 20."); case 20: .. case 29: writeln("Less than 30."); break; default: break; } // Output: Less than 20. Less than 30. }I don't know, but ranged case statements don't have the same semantics as giving a range of values when slicing or to a foreach loop, so that may be why. arr[0 .. 10] does _not_ include the element at index 10. case 0: case 10: _does_ include 10. So, it actually probably be a bad thing for them to use the same syntax. To use the same syntax for both would make the semantics of that syntax inconsistent and confusing. - Jonathan M Davis
Aug 17 2011
On 17.08.2011 21:35, Jacob Carlborg wrote:On 2011-08-17 19:48, Jonathan M Davis wrote:int a = 3 .. 5; No need to have run-time assertions for >= 3 && <= 5 Don't we all like compile-time errors?On Wednesday, August 17, 2011 10:27 Vijay Nayar wrote:D should have a built-in range type. One that supports syntax for both including and excluding the last element: auto a = 3 .. 5 auto b = 3 ... 5 Then we wouldn't need a special range syntax for switch statements. You could store ranges in variables and pass them to functions. opSlice probably wouldn't be needed, instead opIndex could be used and you would declare the method to take a range instead of two integers.D adds a very handy feature that allows you to check for a range of values in a single case. Is there a particular reason that the syntax "case<start>: .. case<end>:" is used instead of treating the case statement similarly to an array slice, e.g. "case<start> ..<end>:"? For example: import std.stdio; void main() { int bob = 12; switch (bob) { // Why not "case 0 .. 9:"? case 0: .. case 9: writeln("Less than 10."); case 10: .. case 19: writeln("Less than 20."); case 20: .. case 29: writeln("Less than 30."); break; default: break; } // Output: Less than 20. Less than 30. }I don't know, but ranged case statements don't have the same semantics as giving a range of values when slicing or to a foreach loop, so that may be why. arr[0 .. 10] does _not_ include the element at index 10. case 0: case 10: _does_ include 10. So, it actually probably be a bad thing for them to use the same syntax. To use the same syntax for both would make the semantics of that syntax inconsistent and confusing. - Jonathan M Davis
Aug 17 2011
Am 17.08.2011, 21:49 Uhr, schrieb simendsjo <simendsjo gmail.com>:On 17.08.2011 21:35, Jacob Carlborg wrote:Delphi uses ranges in a way similar to declaring an enum: type TDigit = 0 .. 9; You can then use that in a set, which translates to a Phobos "BitArray": type TDigitSet = set of TDigit; This is now a type that is at least 10 bit long and the usual set operations apply. I liked it to declare types that restrict the set of available values, like a byte but only with the numbers 0 to 100 available. I think it could work like the range checks on arrays. But we are going off-topic here :pOn 2011-08-17 19:48, Jonathan M Davis wrote:int a = 3 .. 5; No need to have run-time assertions for >= 3 && <= 5 Don't we all like compile-time errors?On Wednesday, August 17, 2011 10:27 Vijay Nayar wrote:D should have a built-in range type. One that supports syntax for both including and excluding the last element: auto a = 3 .. 5 auto b = 3 ... 5 Then we wouldn't need a special range syntax for switch statements. You could store ranges in variables and pass them to functions. opSlice probably wouldn't be needed, instead opIndex could be used and you would declare the method to take a range instead of two integers.D adds a very handy feature that allows you to check for a range of values in a single case. Is there a particular reason that the syntax "case<start>: .. case<end>:" is used instead of treating the case statement similarly to an array slice, e.g. "case<start> ..<end>:"? For example: import std.stdio; void main() { int bob = 12; switch (bob) { // Why not "case 0 .. 9:"? case 0: .. case 9: writeln("Less than 10."); case 10: .. case 19: writeln("Less than 20."); case 20: .. case 29: writeln("Less than 30."); break; default: break; } // Output: Less than 20. Less than 30. }I don't know, but ranged case statements don't have the same semantics as giving a range of values when slicing or to a foreach loop, so that may be why. arr[0 .. 10] does _not_ include the element at index 10. case 0: case 10: _does_ include 10. So, it actually probably be a bad thing for them to use the same syntax. To use the same syntax for both would make the semantics of that syntax inconsistent and confusing. - Jonathan M Davis
Aug 18 2011
On 17/08/2011 20:35, Jacob Carlborg wrote:D should have a built-in range type.+1 or maybe +2 if I get an extra vote ;)One that supports syntax for both including and excluding the last element: auto a = 3 .. 5 auto b = 3 ... 5<begin bikeshedding>Then we wouldn't need a special range syntax for switch statements. You could store ranges in variables and pass them to functions. opSlice probably wouldn't be needed, instead opIndex could be used and you would declare the method to take a range instead of two integers.-- Robert http://octarineparrot.com/
Aug 17 2011
On 08/17/2011 09:35 PM, Jacob Carlborg wrote:On 2011-08-17 19:48, Jonathan M Davis wrote:The .. 'operator' is the operator with the lowest precedence in D (it binds even less strongly than ?:), so there is no way auto a = 3 .. 5 can ever work without a breaking language change. But again, 'case range:' matches 'range', not each individual element of 'range' so you'd actually still need a special range syntax for case statements.On Wednesday, August 17, 2011 10:27 Vijay Nayar wrote:D should have a built-in range type. One that supports syntax for both including and excluding the last element: auto a = 3 .. 5 auto b = 3 ... 5 Then we wouldn't need a special range syntax for switch statements. You could store ranges in variables and pass them to functions. opSlice probably wouldn't be needed, instead opIndex could be used and you would declare the method to take a range instead of two integers.D adds a very handy feature that allows you to check for a range of values in a single case. Is there a particular reason that the syntax "case<start>: .. case<end>:" is used instead of treating the case statement similarly to an array slice, e.g. "case<start> ..<end>:"? For example: import std.stdio; void main() { int bob = 12; switch (bob) { // Why not "case 0 .. 9:"? case 0: .. case 9: writeln("Less than 10."); case 10: .. case 19: writeln("Less than 20."); case 20: .. case 29: writeln("Less than 30."); break; default: break; } // Output: Less than 20. Less than 30. }I don't know, but ranged case statements don't have the same semantics as giving a range of values when slicing or to a foreach loop, so that may be why. arr[0 .. 10] does _not_ include the element at index 10. case 0: case 10: _does_ include 10. So, it actually probably be a bad thing for them to use the same syntax. To use the same syntax for both would make the semantics of that syntax inconsistent and confusing. - Jonathan M Davis
Aug 17 2011
On 2011-08-17 21:58, Timon Gehr wrote:On 08/17/2011 09:35 PM, Jacob Carlborg wrote:I don't see either how this could be changed without a breaking language change.D should have a built-in range type. One that supports syntax for both including and excluding the last element: auto a = 3 .. 5 auto b = 3 ... 5 Then we wouldn't need a special range syntax for switch statements. You could store ranges in variables and pass them to functions. opSlice probably wouldn't be needed, instead opIndex could be used and you would declare the method to take a range instead of two integers.The .. 'operator' is the operator with the lowest precedence in D (it binds even less strongly than ?:), so there is no way auto a = 3 .. 5 can ever work without a breaking language change.But again, 'case range:' matches 'range', not each individual element of 'range' so you'd actually still need a special range syntax for case statements.Wouldn't that depend on how it's implemented. -- /Jacob Carlborg
Aug 18 2011
On Wednesday, August 17, 2011 12:35 Jacob Carlborg wrote:On 2011-08-17 19:48, Jonathan M Davis wrote:I suggest that you read the thread that Lars linked to. That type of syntax got shot down essentially for being too easy to confuse .. with ... making it hard to read and easy to screw-up. Regardless, the whole issue got discussed ad naseum there, and the situation definitely isn't going to change for D2, so there really isn't much point in arguing the pros and cons at this point. Maybe there will be something similar in D3 if someone can find an appropriately clear syntax for it, but I'd be very surprised if any such thing happened in D2. - Jonathan M DavisOn Wednesday, August 17, 2011 10:27 Vijay Nayar wrote:D should have a built-in range type. One that supports syntax for both including and excluding the last element: auto a = 3 .. 5 auto b = 3 ... 5 Then we wouldn't need a special range syntax for switch statements. You could store ranges in variables and pass them to functions. opSlice probably wouldn't be needed, instead opIndex could be used and you would declare the method to take a range instead of two integers.D adds a very handy feature that allows you to check for a range of values in a single case. Is there a particular reason that the syntax "case<start>: .. case<end>:" is used instead of treating the case statement similarly to an array slice, e.g. "case<start> ..<end>:"? For example: import std.stdio; void main() { int bob = 12; switch (bob) { // Why not "case 0 .. 9:"? case 0: .. case 9: writeln("Less than 10."); case 10: .. case 19: writeln("Less than 20."); case 20: .. case 29: writeln("Less than 30."); break; default: break; } // Output: Less than 20. Less than 30. }I don't know, but ranged case statements don't have the same semantics as giving a range of values when slicing or to a foreach loop, so that may be why. arr[0 .. 10] does _not_ include the element at index 10. case 0: case 10: _does_ include 10. So, it actually probably be a bad thing for them to use the same syntax. To use the same syntax for both would make the semantics of that syntax inconsistent and confusing. - Jonathan M Davis
Aug 17 2011
On 2011-08-17 22:00, Jonathan M Davis wrote:On Wednesday, August 17, 2011 12:35 Jacob Carlborg wrote:Yes I know that it has been discussed before. We don't have to discuss this again, I'm just telling my opinion and I don't agree with .. and ... being confusing. -- /Jacob CarlborgOn 2011-08-17 19:48, Jonathan M Davis wrote:I suggest that you read the thread that Lars linked to. That type of syntax got shot down essentially for being too easy to confuse .. with ... making it hard to read and easy to screw-up. Regardless, the whole issue got discussed ad naseum there, and the situation definitely isn't going to change for D2, so there really isn't much point in arguing the pros and cons at this point. Maybe there will be something similar in D3 if someone can find an appropriately clear syntax for it, but I'd be very surprised if any such thing happened in D2. - Jonathan M DavisOn Wednesday, August 17, 2011 10:27 Vijay Nayar wrote:D should have a built-in range type. One that supports syntax for both including and excluding the last element: auto a = 3 .. 5 auto b = 3 ... 5 Then we wouldn't need a special range syntax for switch statements. You could store ranges in variables and pass them to functions. opSlice probably wouldn't be needed, instead opIndex could be used and you would declare the method to take a range instead of two integers.D adds a very handy feature that allows you to check for a range of values in a single case. Is there a particular reason that the syntax "case<start>: .. case<end>:" is used instead of treating the case statement similarly to an array slice, e.g. "case<start> ..<end>:"? For example: import std.stdio; void main() { int bob = 12; switch (bob) { // Why not "case 0 .. 9:"? case 0: .. case 9: writeln("Less than 10."); case 10: .. case 19: writeln("Less than 20."); case 20: .. case 29: writeln("Less than 30."); break; default: break; } // Output: Less than 20. Less than 30. }I don't know, but ranged case statements don't have the same semantics as giving a range of values when slicing or to a foreach loop, so that may be why. arr[0 .. 10] does _not_ include the element at index 10. case 0: case 10: _does_ include 10. So, it actually probably be a bad thing for them to use the same syntax. To use the same syntax for both would make the semantics of that syntax inconsistent and confusing. - Jonathan M Davis
Aug 18 2011
On 2011-08-17 22:00, Jonathan M Davis wrote:I suggest that you read the thread that Lars linked to. That type of syntax got shot down essentially for being too easy to confuse .. with ... making it hard to read and easy to screw-up. Regardless, the whole issue got discussed ad naseum there, and the situation definitely isn't going to change for D2, so there really isn't much point in arguing the pros and cons at this point. Maybe there will be something similar in D3 if someone can find an appropriately clear syntax for it, but I'd be very surprised if any such thing happened in D2. - Jonathan M DavisBTW, I think it would be more useful to have a built-in type for ranges then syntax for both inclusive and exclusive end. -- /Jacob Carlborg
Aug 18 2011
Jacob Carlborg:D should have a built-in range type. One that supports syntax for both including and excluding the last element: auto a = 3 .. 5 auto b = 3 ... 5 Then we wouldn't need a special range syntax for switch statements.Regarding just switches, GCC has a non standard syntax extension that allows you to write case 'a' ... 'z': http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_5.html#SEC90 But it also says:Note: Always write spaces around the ..., for otherwise it may be parsed wrong when you use it with integer values. For example, write this: case 1 ... 5: rather than this: case 1...5:Bye, bearophile
Aug 17 2011
On Wed, 17 Aug 2011 16:29:19 -0400, bearophile wrote:Jacob Carlborg:That's pretty clever. They recognized the ambiguity problem of misinterpreting a string like "5...5" as either "5. .. 5", "5 .. .5" or something else by requiring spaces around the '...' operator. Quoting from the above link:D should have a built-in range type. One that supports syntax for both including and excluding the last element: auto a = 3 .. 5 auto b = 3 ... 5 Then we wouldn't need a special range syntax for switch statements.Regarding just switches, GCC has a non standard syntax extension that allows you to write case 'a' ... 'z': http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_5.html#SEC90 But it also says:Note: Always write spaces around the ..., for otherwise it may be parsed wrong when you use it with integer values. For example, write this: case 1 ... 5: rather than this: case 1...5:Bye, bearophileBe careful: Write spaces around the ..., for otherwise it may be parsed wrong when you use it with integer values. For example, write this: case 1 ... 5: rather than this: case 1...5:Or maybe I'm just easily impressed :) What can I say, it was the death- by-a-thousand-cuts in C++ that pushed to find a better compiled language in the first place. - Vijay
Aug 17 2011
On 8/17/11 2:35 PM, Jacob Carlborg wrote:On 2011-08-17 19:48, Jonathan M Davis wrote:I doubt that would work well. Let's ignore for now mundane issues such as the ambiguity of 3...5 and focus on something like: int x; ... switch (x) { case 3 ... 5: return 1; default: return 0; } We'd need to change the behavior of switch anyway, or we'd need to define equality such that e.g. 4 == 3 ... 5. But then equality is not transitive anymore because 4 == 2 ... 6 too, but 3 ... 5 is not equal to 2 ... 6. Adding new built-in types is not easy. For a variety of reasons we should move the other way (per e.g. the hashtables discussion elsethread). AndreiOn Wednesday, August 17, 2011 10:27 Vijay Nayar wrote:D should have a built-in range type. One that supports syntax for both including and excluding the last element: auto a = 3 .. 5 auto b = 3 ... 5 Then we wouldn't need a special range syntax for switch statements. You could store ranges in variables and pass them to functions. opSlice probably wouldn't be needed, instead opIndex could be used and you would declare the method to take a range instead of two integers.D adds a very handy feature that allows you to check for a range of values in a single case. Is there a particular reason that the syntax "case<start>: .. case<end>:" is used instead of treating the case statement similarly to an array slice, e.g. "case<start> ..<end>:"? For example: import std.stdio; void main() { int bob = 12; switch (bob) { // Why not "case 0 .. 9:"? case 0: .. case 9: writeln("Less than 10."); case 10: .. case 19: writeln("Less than 20."); case 20: .. case 29: writeln("Less than 30."); break; default: break; } // Output: Less than 20. Less than 30. }I don't know, but ranged case statements don't have the same semantics as giving a range of values when slicing or to a foreach loop, so that may be why. arr[0 .. 10] does _not_ include the element at index 10. case 0: case 10: _does_ include 10. So, it actually probably be a bad thing for them to use the same syntax. To use the same syntax for both would make the semantics of that syntax inconsistent and confusing. - Jonathan M Davis
Aug 17 2011
On 2011-08-18 00:51, Andrei Alexandrescu wrote:On 8/17/11 2:35 PM, Jacob Carlborg wrote:I'm just hoping that floating point syntax will be removed. I know a lot of people agree with me on this.D should have a built-in range type. One that supports syntax for both including and excluding the last element: auto a = 3 .. 5 auto b = 3 ... 5 Then we wouldn't need a special range syntax for switch statements. You could store ranges in variables and pass them to functions. opSlice probably wouldn't be needed, instead opIndex could be used and you would declare the method to take a range instead of two integers.I doubt that would work well. Let's ignore for now mundane issues such as the ambiguity of 3...5 and focus on something like:int x; ... switch (x) { case 3 ... 5: return 1; default: return 0; } We'd need to change the behavior of switch anyway, or we'd need to define equality such that e.g. 4 == 3 ... 5. But then equality is not transitive anymore because 4 == 2 ... 6 too, but 3 ... 5 is not equal to 2 ... 6.There could be some kind of "include" function/property or similar. Just as there are built-in properties on other types in D.Adding new built-in types is not easy. For a variety of reasons we should move the other way (per e.g. the hashtables discussion elsethread). AndreiI know that the implementation of the associative arrays have been moved to the runtime, if you're referring to that. But the compiler still knows about the associative array, right? I don't care where a range type would be implemented, in the compiler or in the runtime. -- /Jacob Carlborg
Aug 18 2011
On 8/18/11 6:42 AM, Jacob Carlborg wrote:On 2011-08-18 00:51, Andrei Alexandrescu wrote:There could be indeed a lot of things. My point is that there _need_ to be such. It's not a simple, minute addition.On 8/17/11 2:35 PM, Jacob Carlborg wrote:I'm just hoping that floating point syntax will be removed. I know a lot of people agree with me on this.D should have a built-in range type. One that supports syntax for both including and excluding the last element: auto a = 3 .. 5 auto b = 3 ... 5 Then we wouldn't need a special range syntax for switch statements. You could store ranges in variables and pass them to functions. opSlice probably wouldn't be needed, instead opIndex could be used and you would declare the method to take a range instead of two integers.I doubt that would work well. Let's ignore for now mundane issues such as the ambiguity of 3...5 and focus on something like:int x; ... switch (x) { case 3 ... 5: return 1; default: return 0; } We'd need to change the behavior of switch anyway, or we'd need to define equality such that e.g. 4 == 3 ... 5. But then equality is not transitive anymore because 4 == 2 ... 6 too, but 3 ... 5 is not equal to 2 ... 6.There could be some kind of "include" function/property or similar. Just as there are built-in properties on other types in D.I'm not talking about an implementation difficulty, but about semantics difficulties within the language. My point is that although the feature superficially looks easy to add and nice to have, in reality there are a lot of subtle additional changes we must make to the language semantics. AndreiAdding new built-in types is not easy. For a variety of reasons we should move the other way (per e.g. the hashtables discussion elsethread). AndreiI know that the implementation of the associative arrays have been moved to the runtime, if you're referring to that. But the compiler still knows about the associative array, right? I don't care where a range type would be implemented, in the compiler or in the runtime.
Aug 18 2011
On 2011-08-18 15:36, Andrei Alexandrescu wrote:On 8/18/11 6:42 AM, Jacob Carlborg wrote:Ok, we can stop this discussion. In my original post I was just trying to say that it's a pity that D doesn't have a built-in range type and if it was three, four years ago it could have been added to the language, perhaps. I could have avoided a few, in my opinion, "hacks", like the case ranges. I fully understand if this feature cannot be added to the language now. -- /Jacob CarlborgOn 2011-08-18 00:51, Andrei Alexandrescu wrote:There could be indeed a lot of things. My point is that there _need_ to be such. It's not a simple, minute addition.On 8/17/11 2:35 PM, Jacob Carlborg wrote:I'm just hoping that floating point syntax will be removed. I know a lot of people agree with me on this.D should have a built-in range type. One that supports syntax for both including and excluding the last element: auto a = 3 .. 5 auto b = 3 ... 5 Then we wouldn't need a special range syntax for switch statements. You could store ranges in variables and pass them to functions. opSlice probably wouldn't be needed, instead opIndex could be used and you would declare the method to take a range instead of two integers.I doubt that would work well. Let's ignore for now mundane issues such as the ambiguity of 3...5 and focus on something like:int x; ... switch (x) { case 3 ... 5: return 1; default: return 0; } We'd need to change the behavior of switch anyway, or we'd need to define equality such that e.g. 4 == 3 ... 5. But then equality is not transitive anymore because 4 == 2 ... 6 too, but 3 ... 5 is not equal to 2 ... 6.There could be some kind of "include" function/property or similar. Just as there are built-in properties on other types in D.I'm not talking about an implementation difficulty, but about semantics difficulties within the language. My point is that although the feature superficially looks easy to add and nice to have, in reality there are a lot of subtle additional changes we must make to the language semantics. AndreiAdding new built-in types is not easy. For a variety of reasons we should move the other way (per e.g. the hashtables discussion elsethread). AndreiI know that the implementation of the associative arrays have been moved to the runtime, if you're referring to that. But the compiler still knows about the associative array, right? I don't care where a range type would be implemented, in the compiler or in the runtime.
Aug 18 2011
On Wed, 17 Aug 2011 17:51:48 -0500, Andrei Alexandrescu wrote:I doubt that would work well. Let's ignore for now mundane issues such as the ambiguity of 3...5 and focus on something like: int x; ... switch (x) { case 3 ... 5: return 1; default: return 0; } We'd need to change the behavior of switch anyway, or we'd need to define equality such that e.g. 4 == 3 ... 5. But then equality is not transitive anymore because 4 == 2 ... 6 too, but 3 ... 5 is not equal to 2 ... 6. Adding new built-in types is not easy. For a variety of reasons we should move the other way (per e.g. the hashtables discussion elsethread). AndreiFrom this discussion, I gather that the 'switch' statement is effectively using '==' to compare to each 'case' statement value (I didn't know that's how it worked). Andrei, you are very good at explaining concepts in plain English, and I was hoping you could explain what D is seeing when it sees the 'case A: .. case B:' syntax. My current understanding is that 'switch' is effectively iterating through all it's top-level tokens, which are 'case', '..', and 'default', in a manner similar to a for-loop. The special top-level token '..' is interpreted to effectively turn into new 'case' tokens starting from the last seen 'case' and ending when the next 'case' is seen. Is that correct? Does the D 'switch' statement replace the '..' token with a bunch of 'case' tokens, thus allowing the 'swtich' hash-lookup to work quickly and efficiently? - Vijay
Aug 18 2011
On 8/18/11 10:02 AM, Vijay Nayar wrote:On Wed, 17 Aug 2011 17:51:48 -0500, Andrei Alexandrescu wrote:The exact behavior is dependent on the compiler implementation. Essentially, yes, switch is recommended when you have branches of comparable probability, but don't read too much into specific implementation mechanisms, and don't mix language semantics with grammar minutia. AndreiI doubt that would work well. Let's ignore for now mundane issues such as the ambiguity of 3...5 and focus on something like: int x; ... switch (x) { case 3 ... 5: return 1; default: return 0; } We'd need to change the behavior of switch anyway, or we'd need to define equality such that e.g. 4 == 3 ... 5. But then equality is not transitive anymore because 4 == 2 ... 6 too, but 3 ... 5 is not equal to 2 ... 6. Adding new built-in types is not easy. For a variety of reasons we should move the other way (per e.g. the hashtables discussion elsethread). AndreiFrom this discussion, I gather that the 'switch' statement is effectively using '==' to compare to each 'case' statement value (I didn't know that's how it worked). Andrei, you are very good at explaining concepts in plain English, and I was hoping you could explain what D is seeing when it sees the 'case A: .. case B:' syntax. My current understanding is that 'switch' is effectively iterating through all it's top-level tokens, which are 'case', '..', and 'default', in a manner similar to a for-loop. The special top-level token '..' is interpreted to effectively turn into new 'case' tokens starting from the last seen 'case' and ending when the next 'case' is seen. Is that correct? Does the D 'switch' statement replace the '..' token with a bunch of 'case' tokens, thus allowing the 'swtich' hash-lookup to work quickly and efficiently? - Vijay
Aug 18 2011
Vijay Nayar wrote:On Wed, 17 Aug 2011 17:51:48 -0500, Andrei Alexandrescu wrote:Yes. That's why the maximum length of the range is currently limited to 256 cases. Something like: case 0: .. case int.max: break; won't currently compile.I doubt that would work well. Let's ignore for now mundane issues such as the ambiguity of 3...5 and focus on something like: int x; ... switch (x) { case 3 ... 5: return 1; default: return 0; } We'd need to change the behavior of switch anyway, or we'd need to define equality such that e.g. 4 == 3 ... 5. But then equality is not transitive anymore because 4 == 2 ... 6 too, but 3 ... 5 is not equal to 2 ... 6. Adding new built-in types is not easy. For a variety of reasons we should move the other way (per e.g. the hashtables discussion elsethread). AndreiFrom this discussion, I gather that the 'switch' statement is effectively using '==' to compare to each 'case' statement value (I didn't know that's how it worked). Andrei, you are very good at explaining concepts in plain English, and I was hoping you could explain what D is seeing when it sees the 'case A: .. case B:' syntax. My current understanding is that 'switch' is effectively iterating through all it's top-level tokens, which are 'case', '..', and 'default', in a manner similar to a for-loop. The special top-level token '..' is interpreted to effectively turn into new 'case' tokens starting from the last seen 'case' and ending when the next 'case' is seen. Is that correct? Does the D 'switch' statement replace the '..' token with a bunch of 'case' tokens, thus allowing the 'swtich' hash-lookup to work quickly and efficiently?
Aug 18 2011
On 08/17/2011 07:27 PM, Vijay Nayar wrote:D adds a very handy feature that allows you to check for a range of values in a single case. Is there a particular reason that the syntax "case<start>: .. case<end>:" is used instead of treating the case statement similarly to an array slice, e.g. "case<start> ..<end>:"? For example: import std.stdio; void main() { int bob = 12; switch (bob) { // Why not "case 0 .. 9:"? case 0: .. case 9: writeln("Less than 10."); case 10: .. case 19: writeln("Less than 20."); case 20: .. case 29: writeln("Less than 30."); break; default: break; } // Output: Less than 20. Less than 30. } - VijayWith the other syntax, the wrapping switch statement really should look like this: switch(a .. b){ case x .. y: // a case statement that matches a range } as opposed to: switch(a){ case x: .. case y: // a range of case statements }
Aug 17 2011