digitalmars.D - Improvement to switch-case statement
- Mike James (11/11) Dec 31 2008 Just an idea that could improve Ds switch-case statement - add an elipsy...
- Jarrett Billingsley (7/17) Dec 31 2008 It's such a common need, and such a simple thing to implement, that
- Yigal Chripun (8/19) Dec 31 2008 vote--
- Adam D. Ruppe (56/59) Dec 31 2008 This wouldn't be any less efficient than any other switch statement; wri...
- bearophile (14/25) Dec 31 2008 Note that the following syntax is already possible in D:
- Michel Fortin (16/30) Dec 31 2008 Except that if you want to keep consistency with array slices, 2..5
- John Reimer (5/36) Dec 31 2008 Good point. So while the '..' is potentially useful, it may just be sim...
- John Reimer (6/41) Dec 31 2008 Of course, here it seems we're starting to enter the domain of regular e...
- bearophile (7/19) Dec 31 2008 Ruby solves the problem having two different syntaxed, .. and ... for op...
- Daniel Keep (7/42) Dec 31 2008 Python solves this rather elegantly; instead of
- Nick Sabalausky (6/47) Jan 01 2009 Not a bad idea. How does it handle something like this:
- Jarrett Billingsley (9/13) Jan 01 2009 From the Python docs:
- John Reimer (14/41) Dec 31 2008 Well, the D switch statement has already abandoned the low-level C const...
- John Reimer (3/6) Dec 31 2008 Er... pardon... I don't think that would work with CTFI.
- Yigal Chripun (6/49) Dec 31 2008 D's switch is indeed better than C already but it still is rather
- John Reimer (6/64) Dec 31 2008 True, a case statment can take a comma-separated expression list like th...
- Stewart Gordon (9/15) Jan 02 2009 What would a "general mechanism of pattern matching" involve, and how
- BCS (9/30) Jan 02 2009 I for one don't like that proposal for a few reasons:
- Stewart Gordon (15/36) Jan 02 2009 Please read that proposal properly. You'll see that it supports
- BCS (20/55) Jan 02 2009 Duff's device is actualy one of the use cases I'm thinking of. However m...
- Yigal Chripun (38/53) Jan 02 2009 I have several idea on this, nothing finished though:
- bearophile (9/12) Jan 02 2009 But a ternary operator is sometimes handy: when used judiciously it may ...
- Yigal Chripun (16/28) Jan 02 2009 Sorry, I guess I wasn't clear. I meant to say: remove the *current*
- Adam D. Ruppe (7/10) Jan 02 2009 Don't forget that D isn't a "real OOP language" - it specifically is mad...
- John Reimer (4/17) Jan 02 2009 Yeah, I was just going to say that Smalltalk is the epitome of a pure OO...
- Benji Smith (8/12) Jan 02 2009 Interesting...
- Yigal Chripun (24/36) Jan 03 2009 Simple. using polymorphism and closures (called blocks in Smalltalk).
- Benji Smith (21/24) Jan 02 2009 Heresy!
- Nick Sabalausky (19/43) Jan 03 2009 Right. I use ?: constantly. I can't stand having my code littered with t...
- Stewart Gordon (12/51) Jan 03 2009 So you make the () required so that the {} can be optional. At least
- Yigal Chripun (22/73) Jan 03 2009 like I said, this is just my first attempt...
Just an idea that could improve Ds switch-case statement - add an elipsys as in object Pascal to allow case ranges. switch (var) { case 1: \\ do something break; case 2..10: \\ do something else break; } What do people think? -=mike=-
Dec 31 2008
On Wed, Dec 31, 2008 at 5:16 PM, Mike James <foo bar.com> wrote:Just an idea that could improve Ds switch-case statement - add an elipsys as in object Pascal to allow case ranges. switch (var) { case 1: \\ do something break; case 2..10: \\ do something else break; } What do people think?It's such a common need, and such a simple thing to implement, that I'm absolutely shocked that more languages _haven't_ adopted it. It's annoying when you're writing some kind of string parser and have to put all sorts of stuff in the 'default' that could easily be handled by cases like this. In fact, I'll put it in MiniD right now. Geez.
Dec 31 2008
Mike James wrote:Just an idea that could improve Ds switch-case statement - add an elipsys as in object Pascal to allow case ranges. switch (var) { case 1: \\ do something break; case 2..10: \\ do something else break; } What do people think? -=mike=-vote-- IMO, either the switch statement should remain the low level (effiecient) construct as in C, or replaced by a general mechanism of pattern matching. your solution is kinda between the two above options and I don't see the point of it. I'd personally prefer pattern matching to be added to D and the switch to be deprecated and eventually removed from the language.
Dec 31 2008
On Thu, Jan 01, 2009 at 12:45:39AM +0200, Yigal Chripun wrote:IMO, either the switch statement should remain the low level (effiecient) construct as in C, or replaced by a general mechanism of pattern matching.This wouldn't be any less efficient than any other switch statement; writing case 2..5: code; break; could just be magically converted into case 2: case 3: case 4: case 5: code; break; That's not ideal when doing a huge range; I'd probably write it like so in asm: cmp ax, 2 je code cmp ax, 3 je code cmp ax, 4 je code cmp ax, 5 je code ; more cases.... jmp default code: ; the code from inside the case goes here Doing a bigger range could let you write something more like this: cmp ax, 2 jl more_cases cmp ax, 5 jg more_cases ; case 2..5 code here more_cases: ; check other cases jmp default Or maybe: cmp ax, 2 jge code more_cases: ; more cases.... jmp default code: cmp ax, 5 jg more_cases ; proceed with the code inside If I was writing it by hand, I'd probably pick one based on what other cases there are to try and minimize the jumps. The compiler could surely do the same. Anyway though, the point is the simple range in the case is at least no worse than writing it in C with a series of cases, and might be better, since the compiler can condense it all down into just a few instructions rather than a big laundry list. Finally, the D switch statement already does strings as cases, which the one in C would never do; the D switch already has moved beyond it, so it wouldn't be out of character for it to pick up the ranges too. -- Adam D. Ruppe http://arsdnet.net
Dec 31 2008
Adam D. Ruppe:case 2..5: code; break; could just be magically converted into case 2: case 3: case 4: case 5: code; break;Note that the following syntax is already possible in D: case 2,3,4,5: code; break; But the range gets larger that syntax gets ugly, so the .. range looks like a good thing to have. So I'm +1 on the idea of the original poster. The range syntax of the D2 foreach may be even extended to support: if (x in 10..20) {... That more or less equals to the C macro: #define InRange(x, a, b) (unsigned((x) - (a)) <= (b) - (a)) That as you can see has just one branch instead of the usual two: http://smallcode.weblogs.us/checking_if_point_belongs_to_interval Bye, bearophile
Dec 31 2008
On 2008-12-31 18:22:32 -0500, "Adam D. Ruppe" <destructionator gmail.com> said:This wouldn't be any less efficient than any other switch statement; writing case 2..5: code; break; could just be magically converted into case 2: case 3: case 4: case 5: code; break;Except that if you want to keep consistency with array slices, 2..5 should probably not include 5 in the range, thus should be equivalent "case 2,3,4". Unfortunatly, that's generally not what you want when creating such cases. Imagine writting: case 'a'..'{': case 'A'..'[': Concistent, yes; but not very appealing. What you want to be able to write is this: case 'a'..'z': case 'A'..'Z': But then it doesn't work as elsewhere in the language anymore. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Dec 31 2008
Hello Michel,On 2008-12-31 18:22:32 -0500, "Adam D. Ruppe" <destructionator gmail.com> said:Good point. So while the '..' is potentially useful, it may just be simpler to implement something like a range macro rather than suffer the risk of such an inconsistancy. -JJRThis wouldn't be any less efficient than any other switch statement; writing case 2..5: code; break; could just be magically converted into case 2: case 3: case 4: case 5: code; break;Except that if you want to keep consistency with array slices, 2..5 should probably not include 5 in the range, thus should be equivalent "case 2,3,4". Unfortunatly, that's generally not what you want when creating such cases. Imagine writting: case 'a'..'{': case 'A'..'[': Concistent, yes; but not very appealing. What you want to be able to write is this: case 'a'..'z': case 'A'..'Z': But then it doesn't work as elsewhere in the language anymore.
Dec 31 2008
Hello John,Hello Michel,Of course, here it seems we're starting to enter the domain of regular expression parsing anyway, so it leaves one wondering if it's worth fixing up the switch statement too much for this. :) Very likely better to pursue a macro-like epression here. -JJROn 2008-12-31 18:22:32 -0500, "Adam D. Ruppe" <destructionator gmail.com> said:Good point. So while the '..' is potentially useful, it may just be simpler to implement something like a range macro rather than suffer the risk of such an inconsistancy. -JJRThis wouldn't be any less efficient than any other switch statement; writing case 2..5: code; break; could just be magically converted into case 2: case 3: case 4: case 5: code; break;Except that if you want to keep consistency with array slices, 2..5 should probably not include 5 in the range, thus should be equivalent "case 2,3,4". Unfortunatly, that's generally not what you want when creating such cases. Imagine writting: case 'a'..'{': case 'A'..'[': Concistent, yes; but not very appealing. What you want to be able to write is this: case 'a'..'z': case 'A'..'Z': But then it doesn't work as elsewhere in the language anymore.
Dec 31 2008
Michel Fortin Wrote:Imagine writting: case 'a'..'{': case 'A'..'[': Concistent, yes; but not very appealing. What you want to be able to write is this: case 'a'..'z': case 'A'..'Z': But then it doesn't work as elsewhere in the language anymore.Ruby solves the problem having two different syntaxed, .. and ... for open and closed intervals. But I don't like it much, it's easy to miss the extra point. An easy solution: case 'a' .. 'z'+1: case 'A' .. 'Z'+1: Bye, bearophile
Dec 31 2008
Michel Fortin wrote:On 2008-12-31 18:22:32 -0500, "Adam D. Ruppe" <destructionator gmail.com> said:Python solves this rather elegantly; instead of if( chr in 2..5 ) ... you can just do this: if( 2 <= chr <= 5 ) ... which allows you to explicitly control which ends are inclusive/exclusive. -- DanielThis wouldn't be any less efficient than any other switch statement; writing case 2..5: code; break; could just be magically converted into case 2: case 3: case 4: case 5: code; break;Except that if you want to keep consistency with array slices, 2..5 should probably not include 5 in the range, thus should be equivalent "case 2,3,4". Unfortunatly, that's generally not what you want when creating such cases. Imagine writting: case 'a'..'{': case 'A'..'[': Concistent, yes; but not very appealing. What you want to be able to write is this: case 'a'..'z': case 'A'..'Z': But then it doesn't work as elsewhere in the language anymore.
Dec 31 2008
"Daniel Keep" <daniel.keep.lists gmail.com> wrote in message news:gjhapq$171v$1 digitalmars.com...Michel Fortin wrote:Not a bad idea. How does it handle something like this: if( a > b < c) Is that an error? Or does it get split into: if( a > b && b < c)On 2008-12-31 18:22:32 -0500, "Adam D. Ruppe" <destructionator gmail.com> said:Python solves this rather elegantly; instead of if( chr in 2..5 ) ... you can just do this: if( 2 <= chr <= 5 ) ... which allows you to explicitly control which ends are inclusive/exclusive.This wouldn't be any less efficient than any other switch statement; writing case 2..5: code; break; could just be magically converted into case 2: case 3: case 4: case 5: code; break;Except that if you want to keep consistency with array slices, 2..5 should probably not include 5 in the range, thus should be equivalent "case 2,3,4". Unfortunatly, that's generally not what you want when creating such cases. Imagine writting: case 'a'..'{': case 'A'..'[': Concistent, yes; but not very appealing. What you want to be able to write is this: case 'a'..'z': case 'A'..'Z': But then it doesn't work as elsewhere in the language anymore.
Jan 01 2009
On Thu, Jan 1, 2009 at 12:45 PM, Nick Sabalausky <a a.a> wrote:Not a bad idea. How does it handle something like this: if( a > b < c) Is that an error? Or does it get split into: if( a > b && b < c)From the Python docs: "Formally, if a, b, c, ..., y, z are expressions and opa, opb, ..., opy are comparison operators, then a opa b opb c ...y opy z is equivalent to a opa b and b opb c and ... y opy z, except that each expression is evaluated at most once. Note that a opa b opb c doesn't imply any kind of comparison between a and c, so that, e.g., x < y > z is perfectly legal (though perhaps not pretty). "
Jan 01 2009
Hello Yigal,Mike James wrote:Well, the D switch statement has already abandoned the low-level C construct in that it allows for switching on strings. I don't think there is a reason to believe that adding the range feature would mean a loss of efficiency. I have to agree that this would appear to be a fairly simple and useful feature that exists in other "old" languages like Pascal and derivitives. I'm not sure why it was left out in D, but I wouldn't be a bit surprised if the request has been made before. On the other hand, it probably wouldn't be hard to implement a range as a compile time template (or plain) function inserted after the case statement: case range(2,10): // But then again... since array slices make use of "..", it seems a shame that it can't also be used in the case statement for a similar purpose. -JJRJust an idea that could improve Ds switch-case statement - add an elipsys as in object Pascal to allow case ranges. switch (var) { case 1: \\ do something break; case 2..10: \\ do something else break; } What do people think? -=mike=-vote-- IMO, either the switch statement should remain the low level (effiecient) construct as in C, or replaced by a general mechanism of pattern matching. your solution is kinda between the two above options and I don't see the point of it. I'd personally prefer pattern matching to be added to D and the switch to be deprecated and eventually removed from the language.
Dec 31 2008
case range(2,10): //Er... pardon... I don't think that would work with CTFI. I was thinking too quickly on that one. :P -JJR
Dec 31 2008
John Reimer wrote:Hello Yigal,D's switch is indeed better than C already but it still is rather low-level at least from a syntax point of view: it uses labels and break. Can the current switch be extended to support full pattern matching without conflicting with the current syntax? what about specifying alist of values, like: case 1,2,3:...Mike James wrote:Well, the D switch statement has already abandoned the low-level C construct in that it allows for switching on strings. I don't think there is a reason to believe that adding the range feature would mean a loss of efficiency. I have to agree that this would appear to be a fairly simple and useful feature that exists in other "old" languages like Pascal and derivitives. I'm not sure why it was left out in D, but I wouldn't be a bit surprised if the request has been made before. On the other hand, it probably wouldn't be hard to implement a range as a compile time template (or plain) function inserted after the case statement: case range(2,10): // But then again... since array slices make use of "..", it seems a shame that it can't also be used in the case statement for a similar purpose. -JJRJust an idea that could improve Ds switch-case statement - add an elipsys as in object Pascal to allow case ranges. switch (var) { case 1: \\ do something break; case 2..10: \\ do something else break; } What do people think? -=mike=-vote-- IMO, either the switch statement should remain the low level (effiecient) construct as in C, or replaced by a general mechanism of pattern matching. your solution is kinda between the two above options and I don't see the point of it. I'd personally prefer pattern matching to be added to D and the switch to be deprecated and eventually removed from the language.
Dec 31 2008
Hello Yigal,John Reimer wrote:True, a case statment can take a comma-separated expression list like that, so maybe there is an opportunity for a compile-time template mixin or something afterall. I forgot about the comma op. That's makes things a little more promising. -JJRHello Yigal,D's switch is indeed better than C already but it still is rather low-level at least from a syntax point of view: it uses labels and break. Can the current switch be extended to support full pattern matching without conflicting with the current syntax? what about specifying alist of values, like: case 1,2,3:...Mike James wrote:Well, the D switch statement has already abandoned the low-level C construct in that it allows for switching on strings. I don't think there is a reason to believe that adding the range feature would mean a loss of efficiency. I have to agree that this would appear to be a fairly simple and useful feature that exists in other "old" languages like Pascal and derivitives. I'm not sure why it was left out in D, but I wouldn't be a bit surprised if the request has been made before. On the other hand, it probably wouldn't be hard to implement a range as a compile time template (or plain) function inserted after the case statement: case range(2,10): // But then again... since array slices make use of "..", it seems a shame that it can't also be used in the case statement for a similar purpose. -JJRJust an idea that could improve Ds switch-case statement - add an elipsys as in object Pascal to allow case ranges. switch (var) { case 1: \\ do something break; case 2..10: \\ do something else break; } What do people think? -=mike=-vote-- IMO, either the switch statement should remain the low level (effiecient) construct as in C, or replaced by a general mechanism of pattern matching. your solution is kinda between the two above options and I don't see the point of it. I'd personally prefer pattern matching to be added to D and the switch to be deprecated and eventually removed from the language.
Dec 31 2008
Yigal Chripun wrote: <snip>IMO, either the switch statement should remain the low level (effiecient) construct as in C, or replaced by a general mechanism of pattern matching. your solution is kinda between the two above options and I don't see the point of it.What would a "general mechanism of pattern matching" involve, and how would it replace switch? Would it replace if as well?I'd personally prefer pattern matching to be added to D and the switch to be deprecated and eventually removed from the language.I'd personally prefer my proposal from years ago to be taken seriously: http://www.digitalmars.com/d/archives/22722.html ISTM silly to improve switch but at the same time keep it restricted to the same old arcane syntax. Stewart.
Jan 02 2009
Reply to Stewart,Yigal Chripun wrote: <snip>I for one don't like that proposal for a few reasons: Because it looses fall through and adding it back in with "goto case n;" gets messy in generated code. I use fall through an some of my template code. Because it can lead to hard to understand code. you need to examine all cases to find the code path rather than just find a single case with the given value. Allowing the same case in more than one place could lead to some extremely hard to find bugs where the same case is added more than once in error.IMO, either the switch statement should remain the low level (effiecient) construct as in C, or replaced by a general mechanism of pattern matching. your solution is kinda between the two above options and I don't see the point of it.What would a "general mechanism of pattern matching" involve, and how would it replace switch? Would it replace if as well?I'd personally prefer pattern matching to be added to D and the switch to be deprecated and eventually removed from the language.I'd personally prefer my proposal from years ago to be taken seriously: http://www.digitalmars.com/d/archives/22722.html ISTM silly to improve switch but at the same time keep it restricted to the same old arcane syntax. Stewart.
Jan 02 2009
BCS wrote:Reply to Stewart,<snip>Please read that proposal properly. You'll see that it supports something more general than fall through. Unless your primary reason for using switch is to implement Duff's device or something like that. Notice also that nowhere did I propose removing the old switch syntax. So if you still want it, it's still there.I'd personally prefer my proposal from years ago to be taken seriously: http://www.digitalmars.com/d/archives/22722.html ISTM silly to improve switch but at the same time keep it restricted to the same old arcane syntax. Stewart.I for one don't like that proposal for a few reasons: Because it looses fall through and adding it back in with "goto case n;" gets messy in generated code. I use fall through an some of my template code.Because it can lead to hard to understand code.I'm sure you could, if you want, write code that is just as obfuscated with the switch we have.you need to examine all cases to find the code path rather than just find a single case with the given value.No I don't. Once I've found a path that matches, I need only to examine those remaining that aren't preceded by else in order to determine whether there are any more.Allowing the same case in more than one place could lead to some extremely hard to find bugs where the same case is added more than once in error.Only if you carry on thinking in terms of C switch. If you think of it as syntactic sugar for if, then it might be easier. Stewart.
Jan 02 2009
Reply to Stewart,BCS wrote:Reply to Stewart,Duff's device is actualy one of the use cases I'm thinking of. However mor generaly I have use for the ability of C's switch to do a "jump into this block at point n" for some runtime n. This is the central device that dparse uses for backtracking. Another use case I can see right off is yield.I for one don't like that proposal for a few reasons: Because it looses fall through and adding it back in with "goto case n;" gets messy in generated code. I use fall through an some of my template code.Please read that proposal properly. You'll see that it supports something more general than fall through. Unless your primary reason for using switch is to implement Duff's device or something like that.Notice also that nowhere did I propose removing the old switch syntax. So if you still want it, it's still there.Ah. I guess I eroneusly assumed that from this threads context.Any obfuscation the current switch can do, the proposal can do as well, however the proposal can do some that the current form can't. Also, the intended use of the proposal tends to add obfuscation IMHO.Because it can lead to hard to understand code.I'm sure you could, if you want, write code that is just as obfuscated with the switch we have.that's still more than one. Also you just pointed out another concern: you need to look at all cases to tell if an else section gets executed. With good tools, not a big problem, OTOH...you need to examine all cases to find the code path rather than just find a single case with the given value.No I don't. Once I've found a path that matches, I need only to examine those remaining that aren't preceded by else in order to determine whether there are any more.What I'm thinking of it as has no bearing on this. Ending up with a second instance of code for a given value when that is incorrect is a bug. If you are pointing out that it can be used as a sequence of "execute this if the value is in this set" blocks then you may have a point, however in that cases I'd say that proposing this in connection with switch is a bad idea as it is to different from switch, and it would tent to imply a "false friend" ( http://en.wikipedia.org/wiki/False_friend )Allowing the same case in more than one place could lead to some extremely hard to find bugs where the same case is added more than once in error.Only if you carry on thinking in terms of C switch. If you think of it as syntactic sugar for if, then it might be easier.
Jan 02 2009
Stewart Gordon wrote:Yigal Chripun wrote: <snip>I have several idea on this, nothing finished though: the only reason for switch in the first place is an optimization in the compiler, besides that, there is no need for it at all and everything can be done with a bunch of if statements. we basically need a way to group several if/case statements together and make them refer the same variable. here's a first attempt: match (value) { case(1) foo(); case(2..4) { foo(); case(3) foo3(); bar(); continue; } case(5) {...} case() {...} // this is the default case } to get the old switch behavior of fall through you use continue. and cases can be nested. I'd say that making cases overlap should be compiler error. the only way it makes sense to me to have overlapping cases is in concurrent code but than the code will need to be marked for that anyway. another related thing, the catch list is also a switch. so instead of the current: try { // put code here } catch (ExceptionA e) { } catch (ExceptionB e) { } catch (ExceptionC e) {} we can extend "case" like this: try { // put code here } catch (e) { case(ExceptionA) handleA(e); case(ExceptionB) handleB(e); case(ExceptionC) handleC(e); case() handleDefault(e); } also, some thought should be spent on getting rid of the ternary op syntax since it interferes with other things that could be added to the language (nullable types, for instance)IMO, either the switch statement should remain the low level (effiecient) construct as in C, or replaced by a general mechanism of pattern matching. your solution is kinda between the two above options and I don't see the point of it.What would a "general mechanism of pattern matching" involve, and how would it replace switch? Would it replace if as well?I'd personally prefer pattern matching to be added to D and the switch to be deprecated and eventually removed from the language.I'd personally prefer my proposal from years ago to be taken seriously: http://www.digitalmars.com/d/archives/22722.html ISTM silly to improve switch but at the same time keep it restricted to the same old arcane syntax. Stewart.
Jan 02 2009
Yigal Chripun:also, some thought should be spent on getting rid of the ternary op syntax since it interferes with other things that could be added to the language (nullable types, for instance)But a ternary operator is sometimes handy: when used judiciously it may help the mind of the person that reads the code to form a "chunk", improving code readability a little. And if you want to modify/remove it you have to remember that D is usually designed to act as C when a C syntax is accepted (even if this leads to some bad things, see the syntax of the "switch" statement or the casting mess). There are many possible alternative syntaxes for the ternary operator. Python in the end has accepted this one: z = 1 if x else y That for example can be used like this: print n, "item" + ("" if a == 1 else "s") Bye, bearophile
Jan 02 2009
bearophile wrote:Yigal Chripun:Sorry, I guess I wasn't clear. I meant to say: remove the *current* syntax of the trenary operator. making "if" an expression is one possible solution to this, as you noted above. Maybe it's just me but all those C-style statements seem so arcane and unnessaccary. real OOP languages do not need control structures to be part of the language - they're part of the class library instead. Here's some Smalltalk examples: (and D-like comparable code) 10 times: [ code ]. // 10.times({ code to be repeated }); map each: [ code ]. // map.each((Type val){ code to be repeated }) (var > 5) ifTrue: [] ifFalse: [] // (var > 5).IfTrueFalse(dgTrue, dgFalse); // reverse the order with a different method of boolean objects var (var > 5) ifFalse: [] ifTrue: [] // use just one of the branches: var (var < 6) ifFalse: [] I guess D is unlikely to adopt the above...also, some thought should be spent on getting rid of the ternary op syntax since it interferes with other things that could be added to the language (nullable types, for instance)But a ternary operator is sometimes handy: when used judiciously it may help the mind of the person that reads the code to form a "chunk", improving code readability a little. And if you want to modify/remove it you have to remember that D is usually designed to act as C when a C syntax is accepted (even if this leads to some bad things, see the syntax of the "switch" statement or the casting mess). There are many possible alternative syntaxes for the ternary operator. Python in the end has accepted this one: z = 1 if x else y That for example can be used like this: print n, "item" + ("" if a == 1 else "s") Bye, bearophile
Jan 02 2009
On Sat, Jan 03, 2009 at 01:36:23AM +0200, Yigal Chripun wrote:Maybe it's just me but all those C-style statements seem so arcane and unnessaccary. real OOP languages do not need control structures to be part of the language - they're part of the class library instead.Don't forget that D isn't a "real OOP language" - it specifically is made to allow several programming styles, and the procedural style is one of them. And I say the language is better for it. -- Adam D. Ruppe http://arsdnet.net
Jan 02 2009
Hello Adam,On Sat, Jan 03, 2009 at 01:36:23AM +0200, Yigal Chripun wrote:Yeah, I was just going to say that Smalltalk is the epitome of a pure OOP language, something D was never meant to be. -JJRMaybe it's just me but all those C-style statements seem so arcane and unnessaccary. real OOP languages do not need control structures to be part of the language - they're part of the class library instead.Don't forget that D isn't a "real OOP language" - it specifically is made to allow several programming styles, and the procedural style is one of them. And I say the language is better for it.
Jan 02 2009
Yigal Chripun wrote:Maybe it's just me but all those C-style statements seem so arcane and unnessaccary. real OOP languages do not need control structures to be part of the language - they're part of the class library instead. Here's some Smalltalk examples: (and D-like comparable code)Interesting... Assuming the core language had no control structures, how would library authors implement them? If the language itself lacked IF, ELSE, SWITCH, CASE, DO, WHILE, FOR, and presumably GOTO... how exactly would you go about implementing them in a library? --benji
Jan 02 2009
Benji Smith wrote:Yigal Chripun wrote:Simple. using polymorphism and closures (called blocks in Smalltalk). for example, Here's a simple D implementation for "if", "else": abstract class Boolean { void IfTrue(void delegate() dg); void IfFalse(void delegate() dg); void IF_ELSE(void delegate() dgTrue, void delegate() dgFalse) { IfTrue(dgTrue); IfFalse(dgFalse); } ... } class True : Boolean { void IfTrue(void delegate() dg) { dg(); } void IfFalse(void delegate() dg) { /* nothing to do here */ } } // class False is implemented similarly you use it like this: (a > 4).IF_ELSE(dg1, dg2); if (a > 4) is "true" it'll be of the type True (in Smalltalk everything is an object, btw) therefore the methods of True will be called - IfTrue will evaluate the delegate, and IfFalse will do nothing.Maybe it's just me but all those C-style statements seem so arcane and unnessaccary. real OOP languages do not need control structures to be part of the language - they're part of the class library instead. Here's some Smalltalk examples: (and D-like comparable code)Interesting... Assuming the core language had no control structures, how would library authors implement them? If the language itself lacked IF, ELSE, SWITCH, CASE, DO, WHILE, FOR, and presumably GOTO... how exactly would you go about implementing them in a library? --benji
Jan 03 2009
Yigal Chripun wrote:also, some thought should be spent on getting rid of the ternary op syntax since it interferes with other things that could be added to the language (nullable types, for instance)Heresy! The ternary operator is one of my favorite tools. If you want to get rid of it, I think you'd have to make the 'if' statement into an expression (which would open up a whole other can of worms). As I showed earlier, there's no ambiguity between the ternary operator and the nullable type suffix. The ambiguity comes from the case statement. In my opinion, the best way to resolve that ambiguity is to add braces around case statments, like this: switch (x) { case 1 { ... } case 2 { ... } default { ... } } But that might make it impossible to implement Duff's Device (blessing or curse? personally, I don't care). And it might imply the creation of a new scope with each case. Currently, a case statement doesn't introduce its own lexical scope. Anyhoo... Don't mess with the ternary operator!! :) --benji
Jan 02 2009
"Benji Smith" <dlanguage benjismith.net> wrote in message news:gjmikc$vos$1 digitalmars.com...Yigal Chripun wrote:Right. I use ?: constantly. I can't stand having my code littered with this sort of obfuscated clutter... if(someFlag) a = 0; else a = b; // Also note, the lvalue is non-DRY char[] outStr; if(a == 0) outStr = "(zero)"; else outStr = "(non-zero)"; Stdout.formatln("blah blah blah {}", outStr); ...when I could just do a nice, neat, clear (can tell at a glance what's going on): a = someFlag? 0 : b; Stdout.formatln("blah blah blah {}", a==0? "zero" : "non-zero");also, some thought should be spent on getting rid of the ternary op syntax since it interferes with other things that could be added to the language (nullable types, for instance)Heresy! The ternary operator is one of my favorite tools. If you want to get rid of it, I think you'd have to make the 'if' statement into an expression (which would open up a whole other can of worms). As I showed earlier, there's no ambiguity between the ternary operator and the nullable type suffix. The ambiguity comes from the case statement. In my opinion, the best way to resolve that ambiguity is to add braces around case statments, like this: switch (x) { case 1 { ... } case 2 { ... } default { ... } } But that might make it impossible to implement Duff's Device (blessing or curse? personally, I don't care). And it might imply the creation of a new scope with each case. Currently, a case statement doesn't introduce its own lexical scope. Anyhoo... Don't mess with the ternary operator!! :) --benji
Jan 03 2009
Stewart Gordon wrote:So you make the () required so that the {} can be optional. At least it's consistent with most other control flow statements this way. I'm not sure why you need to use up another keyword for this - switch would work fine. At least, I don't think it would lead to any parsing ambiguity, though it might take quite a bit of lookahead to determine which switch syntax is being used. Would continue jump straight into the next case block that is a sibling of the current one, whatever it may be, or what? And where there are uncased statements at the same block level as cased statements, under what circumstances will they be executed? Moreover, will "default" still be legal in place of "case()"? Stewart.Yigal Chripun wrote: <snip>I have several idea on this, nothing finished though: the only reason for switch in the first place is an optimization in the compiler, besides that, there is no need for it at all and everything can be done with a bunch of if statements. we basically need a way to group several if/case statements together and make them refer the same variable. here's a first attempt: match (value) { case(1) foo(); case(2..4) { foo(); case(3) foo3(); bar(); continue; } case(5) {...} case() {...} // this is the default case }IMO, either the switch statement should remain the low level (effiecient) construct as in C, or replaced by a general mechanism of pattern matching. your solution is kinda between the two above options and I don't see the point of it.What would a "general mechanism of pattern matching" involve, and how would it replace switch? Would it replace if as well?I'd personally prefer pattern matching to be added to D and the switch to be deprecated and eventually removed from the language.I'd personally prefer my proposal from years ago to be taken seriously: http://www.digitalmars.com/d/archives/22722.html ISTM silly to improve switch but at the same time keep it restricted to the same old arcane syntax. Stewart.
Jan 03 2009
Stewart Gordon wrote:like I said, this is just my first attempt... to answer your questions: 1) new keyword is like you said - to prevent ambiguity, but if the compiler can use "switch" without any parsing dificulties than I'm all for utilizing "switch". 2) requiring () is more consistent with the rest of D - const(..), cast(..), etc... also, this way as you noted, the {} are optional 3) continue should be consistent with loops, so it'll jump to next case in list - like current switch fall-through, (similar to 'continue' to next iteration in loop) and if you nest cases or want to skip a case than you can add a label and continue to that label as well. 4) I'm not sure about 'default' isn't it a waste to make it a keyword just for this? is it used anywhere else in the language? 5) i'm unsure about uncased statements - does it make sense to prohibit those? 6)another thing is adding ability to decompose stuff like in FP, for example: match (arr) { // dynamic array case([a, b]) { use a, b here } // match if array has two elements ... }Stewart Gordon wrote:So you make the () required so that the {} can be optional. At least it's consistent with most other control flow statements this way. I'm not sure why you need to use up another keyword for this - switch would work fine. At least, I don't think it would lead to any parsing ambiguity, though it might take quite a bit of lookahead to determine which switch syntax is being used. Would continue jump straight into the next case block that is a sibling of the current one, whatever it may be, or what? And where there are uncased statements at the same block level as cased statements, under what circumstances will they be executed? Moreover, will "default" still be legal in place of "case()"? Stewart.Yigal Chripun wrote: <snip>I have several idea on this, nothing finished though: the only reason for switch in the first place is an optimization in the compiler, besides that, there is no need for it at all and everything can be done with a bunch of if statements. we basically need a way to group several if/case statements together and make them refer the same variable. here's a first attempt: match (value) { case(1) foo(); case(2..4) { foo(); case(3) foo3(); bar(); continue; } case(5) {...} case() {...} // this is the default case }IMO, either the switch statement should remain the low level (effiecient) construct as in C, or replaced by a general mechanism of pattern matching. your solution is kinda between the two above options and I don't see the point of it.What would a "general mechanism of pattern matching" involve, and how would it replace switch? Would it replace if as well?I'd personally prefer pattern matching to be added to D and the switch to be deprecated and eventually removed from the language.I'd personally prefer my proposal from years ago to be taken seriously: http://www.digitalmars.com/d/archives/22722.html ISTM silly to improve switch but at the same time keep it restricted to the same old arcane syntax. Stewart.
Jan 03 2009