gkz / LiveScript

LiveScript is a language which compiles to JavaScript. It has a straightforward mapping to JavaScript and allows you to write expressive code devoid of repetitive boilerplate. While LiveScript adds many features to assist in functional style programming, it also has many improvements for object oriented and imperative programming.
http://livescript.net
MIT License
2.31k stars 155 forks source link

x ? (y > 0 ? 1 : 2) : 3; // problem in LiveScript #933

Open determin1st opened 7 years ago

determin1st commented 7 years ago

x = if y > 0 then if z > 0 __then 1 __else 2 else 3

Hello, this, i think might be a problem.. Should work.

akubera commented 7 years ago

To restate the problem:

This code fails to compile (with an Error: Parse error on line 4: Unexpected 'ELSE') when you think it should pass; is that correct?

x = if y > 0
  then if z > 0
    then 1
    else 2
  else 3

The bug is else 2 on line 4 is not being "bound" to the associated if+then statements. Compiling after removing that line returns x = y > 0 ? z > 0 ? 1 : 3 : void 8; so it appears the else 3 is associated with the second if, instead of the 3rd.


The 'correct' syntax is to put the entire inner block inside the cascade.

x = if y > 0
  then
    if z > 0
    then 1
    else 2
  else 3

Alternatively, you can group the inner ternary operator with parens to disambiguate the else statements

x = if y > 0
  then (if z > 0
    then 1
    else 2)
  else 3

and x = if y > 0 then (if z > 0 then 1 else 2) else 3.


I'm not sure, but I have a feeling that the problem comes from the ambiguity of the else in the line if a then if b then x else y. Can the compiler check for the presence of a second else (after y) that would be associated with 'if a'?

determin1st commented 7 years ago

Oh, I see. Used your second version of "workaround" with (). I think JS ternary operator style is good (simple), but LiveScript's version more complicated.

foxbunny commented 7 years ago

I think JS ternary operator style is good (simple), but LiveScript's version more complicated.

I feel that having a multi-line if-then block is actually more straightforward from the reader's perspective. JS ternary seems too clever and terse. Of course, LS is the king of terse among the languages targeting JavaScript, but that's not necessarily a good thing either. :)

When I say 'clever' I mean code that looks like "Look ma, no hands!" where the same thing can be expressed using a more common syntax (e.g., if-then block).

ozra commented 7 years ago

I've coded in languages that only has the ternary operator, no if-then, so who's to say what's common syntax ;-)

Anyway, I've never seen then placement like that (well, corresponding, in bash scripts)!

I would spontaneously have written it like so:

x = y > 0 && (z > 0 && 1 || 2) || 3

But as we all know, this is walking on thin ice in JS - but I still find it cleanest. And ofc. in LS: watch out for and/or (would not yield expected result above)

Alternatively, like so:

x = if y > 0 => (if z > 0 => 1 else 2) else 3

And if it must be multi-line, what I think should be the "right" way doesn't work in LS (I find this to be a huge flaw in the language actually!)

# Eaaak - LS can't handle this, boohoo
x = if y > 0
       if z > 0
          1
       else
          2
    else
       3

I see no reason for conflict in allowing the above in the language, so I think it's just a flaw/oversight in the compiler implementation. Anyone enlighten me?

So, in practise, if having to write it multiline, it would perhaps be:

x = if y > 0
   if z > 0
      1
   else
      2
else
   3

But that's not pretty.

determin1st commented 7 years ago

nice comment ozra,

your example: x = y > 0 && (z > 0 && 1 || 2) || 3

looks complicated) and will work with numbers better to my taste. the case, when you need some more cases) in comparison may look more complicated..

suppose, its all about thens aligned with elses.. ternary operator like that:

x = if y > 0 ? if z > 0 ? 1 : 2 : 3

i believe, would be hard work to implement in LS. only the one who know the lexer could possible do that)

ozra commented 7 years ago

The ? operator has an important function in LS - it wouldn't be possible to solve grammatically! You'll simply have to manage without ternary in LS.

pepkin88 commented 6 years ago

That is the only thing I miss from JS syntax, the conciseness of the ternary operator.

If someone's interested, this is how I usually format those operations:

x = if y > 0
  if z > 0
    1
  else 2
else 3

but if I can, and if it fits better, I use the implicit switch (the example shows the equivalent code to the previous one):

x =
  | y <= 0 => 3
  | z <= 0 => 2
  | _      => 1

I hope someone will find it helpful.