elm-lang / elm-plans

no longer in use, just want to keep discussions around
BSD 3-Clause "New" or "Revised" License
29 stars 1 forks source link

Proposal: Merge two-way and multi-way `if` #6

Closed Apanatshka closed 9 years ago

Apanatshka commented 9 years ago

(I thought that would sound friendlier than "Remove" :smiley: )

Proposed change

Merge if-then-else (two-way if) and multi-way if, keeping the best of both.

The dreadful:

if | key == 40 -> n+1
   | key == 38 -> n-1
   | otherwise -> n

Becomes the delightful:

if key == 40 then
    n+1
if key == 38 then
    n-1
else
    n

Two-way ifs would remain valid, but now you can easily add extra branches, basically without having to write else if.

(Other syntax options like -> instead of then or leaving off subsequent ifs can be discussed of course. But this seems the nicest option to me right now. )

Motivation

Having two constructs like this means there are two ways to do things, which is bad (IMHO, I wish I had a link to some article that argues the same).

Pros of two-way if:

Pros of multi-way if:

Cons of multi-way if:

mgold commented 9 years ago

To be clear, the final else is still required, and this is basically avoiding writing else on branches 1 (zero-indexed) to n-1? Then that sounds good to me.

Apanatshka commented 9 years ago

Yes, and I just added the consideration to force rather than allow not writing else on all but the last branch in an if chain. To avoid optional syntax (which I'm against).

mgold commented 9 years ago

I am also against optional syntax in theory, but I don't see how you'd disallow the else. It's a natural use of the 2-way form, and you can use other proposal's syntax in 0.15. You'd certainly need a good compiler error ("omit the else on all but the last conditional" or similar).

So we go from if Bool then a else a to [if Bool then a]+ else a.

Apanatshka commented 9 years ago

I think this is a situation where an awesome error message will be super easy to do. I'll add a motivating example to consideration 3.

rtfeldman commented 9 years ago

To me, the basic tradeoff between this and https://github.com/elm-lang/elm-plans/issues/3 seems to boil down to these benefits and costs:

Benefits:

Costs:

I honestly don't think saving an else worth of characters matters for something that comes up this infrequently; I still have only had occasion to use two-way if expressions in all the Elm code I've written to date.

Similarly I don't know that lining up is a terribly large benefit here...and of course, if it is, you can always add another five spaces after if so that they line up despite the else. That would look a bit weird, granted, but the proposed syntax also looks weird to me because I habitually think "Oh no! An if without an else! I must have messed up my indentation somewhere!"

Personally I value "be less alien" over the conciseness and the lining up here, so I'd prefer #3 to this.

most people haven't seen the then before when not familiar with FP

A bit off-topic, but FYI I've seen then in Ruby, CoffeeScript, Bash Scripting, and good old BASIC, my first programming language. :smile_cat:

Apanatshka commented 9 years ago

Cost 1: is it really that big a cost to learn that you can chain if and leave off the else? Cost 2: Python has elif, so does the C preprocessor and F#, other languages have elseif, Haskell has a multi-way if extension. I don't think this is alien.

I don't think the indentation rules allow you to indent the if 5 spaces and not the else... Even if it did, that would look weird and would never be in the Elm style guide (I imagine).

I'm more susceptible to the argument that an if without else would look wrong, but that's an adjustment you have to make with any new syntax.

I think lining things up if a great benefit that is being dropped in the style guide often enough already for the benefit of nicer textual diffs.

A bit off-topic, but FYI I've seen then in Ruby, CoffeeScript, Bash Scripting, and good old BASIC, my first programming language. :smile_cat:

I guess I don't know my languages well enough then :astonished:

rtfeldman commented 9 years ago

Cost 1 is not that big, but neither benefit is that big either (unless I'm missing something?)

The alienness is a bigger deal for me than either of those. elif and elseif and else if are all different than repeating if; what I meant is that I've never seen a language where you can have if followed by another if and have them be part of the same expression. As far as I know, it's an unprecedented syntax for a common language feature.

Actually a significantly larger problem just occurred to me...this looks like valid JS code - but code that does something completely different!

Consider this valid JS code:

if (condition1)
  console.log("foo");
if (condition2)
  console.log("bar");
else
  console.log("baz");

In JS, if both condition1 and condition2 are truthy, you will get both "foo" and "bar" logged to the console. In this Elm proposal, only the top branch would be followed.

Given that, this seems like it has huge potential for confusion. :crying_cat_face:

z5h commented 9 years ago

Use when instead of if. when and else will line up. It's readable by everyone.

mgold commented 9 years ago

I think the JS code is pretty good evidence against this.

Ruby uses when pattern then result but it's part of a case statement, which in Elm is a separate construct. And I'd like to do this without adding too much more syntax.

rtfeldman commented 9 years ago

CoffeeScript also uses when in case expressions...I think that one would be too confusing.

Apanatshka commented 9 years ago

Ah, the JS example really kills the syntax in this proposal :disappointed: How about no repeated if?

if
  string == "you" then                  -- if string == "you" then
    "what?"                             --   "what?"
  string == "should" then               -- else if string == "should" then
    "hmm"                               --   "hmm"
  string == "have" then                 -- else if string == "have" then
    if
      seenRatRace then                  --   if seenRatRace then
        "I know where this is going"    --     "I know where this is going"
    else                                --   else
      "should have what?"               --     "should have what?"
  string == "bought" then               -- else if string == "bought" then
    "uh oh"                             --   "uh oh"
  string  == "a" then                   -- else if string  == "a" then
    "bag of nuts?"                      --   "bag of nuts?"
  string == "squirrel" then             -- else if string == "squirrel" then
    "ooh.. oh nuts, we're gonna crash"  --   "ooh.. oh nuts, we're gonna crash"
else                                    -- else
  "gah! a skeleton!"                    --   "gah! a skeleton!"

Looks like it would fit the Elm style, it's spaced vertically in a similar way to let.

(I'm not giving up on this yet, I think without distracting extra syntax around this looks much better and easier to read. )

mgold commented 9 years ago

So that's basically taking the current syntax, eliminating the bars, and using else instead of otherwise ->. Hmm.

TheSeamau5 commented 9 years ago

How about arrows like in the case syntax?

if
  string == "you" ->                  
    "what?"                           
  string == "should" ->              
    "hmm"                               
  string == "have" ->                
    if
      seenRatRace ->                  
        "I know where this is going"    
    else ->                         
      "should have what?"               
  string == "bought" ->               
    "uh oh"                            
  string  == "a" ->                  
    "bag of nuts?"                     
  string == "squirrel" ->            
    "ooh.. oh nuts, we're gonna crash"  
else ->                               
  "gah! a skeleton!"                    

(nvm, looks super ugly)

mgold commented 9 years ago

I think we're getting too far afield here. (But that's good, it means we're searching thoroughly.)

Apanatshka commented 9 years ago

@mgold Yes, that's the idea. And distinguishing the then branches and the else branch with different indentation looks nice to me. It seems clearer when you have multiple branches, not strange when you have one (then) branch, and makes it feel similar to the let.

@TheSeamau5 Yeah, the arrow is not better than just using then IMHO. It looks weird on the else, and generally doesn't read as nicely. Since it's always on the end of a sentence and highlighted, the then feels almost as lightweight as ->. (And yes, the arrow looks ugly :P)

evancz commented 9 years ago

I'm closing this repo down. I have this on my personal list of things to do.