January 02, 2009
bearophile wrote:
> 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

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...

January 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
January 03, 2009
BCS wrote:
> Reply to Stewart,
<snip>
>> 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.

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.

> 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.
January 03, 2009
Hello Adam,

> 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.
> 


Yeah, I was just going to say that Smalltalk is the epitome of a pure OOP language, something D was never meant to be.

-JJR 


January 03, 2009
Reply to Stewart,

> BCS wrote:
> 
>> Reply to 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.
>> 
> 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.
> 

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.

> 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.

>> 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.
> 

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.

>> 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.
> 

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...

>> 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.

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 )


January 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
January 03, 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
January 03, 2009
Benji Smith wrote:
> 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

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.
January 03, 2009
> Stewart Gordon wrote:
>> 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.
> 
> 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
> }

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.
January 03, 2009
"Benji Smith" <dlanguage@benjismith.net> wrote in message news:gjmikc$vos$1@digitalmars.com...
> 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

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");