AndreVanDelft / scala

The SubScript extension to the Scala programming language
http://www.subscript-lang.org/
12 stars 1 forks source link

if-then-else operator: too large scope of its operands results in an unintuitive behaviour #54

Closed anatoliykmetyuk closed 9 years ago

anatoliykmetyuk commented 9 years ago

Consider the following script:

  def script live = (
    if (false) then ({println("Hello")})
    {println("World")}
  )

An expected and intuitive behaviour would be an output "World". However, nothing is outputted, since println("World") is also considered to be an operand of then. Same thing happens in case of else:

  def script live = (
    if (false) then ({println("Hello")}) else ({println("Not hello")})
    {println("World")}
  )

Here, println("World") is referred to else.

One workaround is to place a semicolon after the if-then-else statement. A semicolon has higher priority then spaces and does the right thing here:

  def script live = (
    if (false) then ({println("Hello")}) else ({println("Not hello")});
    {println("World")}
  )

Another workaround is to enclose the if-then-else statement into parentheses, which will also do the proper prioritization:

  def script live = (
    (if (true) then ({println("Hello")}) else ({println("Not hello")}))
    {println("World")}
  )

I don't know whether it was intended to work so or maybe it is a bug. But it results in a very unintuitive behaviour and produces errors which are hard to trace. An intuitive behaviour would be to execute just only one operand after then and just one operand after else, not all the operands left in this n-ary operator. In case if many operands need to be executed, one can enclose them in parentheses so that the compiler would treat them as a single operand. This is more intuitive - both for people and for the compiler.

AndreVanDelft commented 9 years ago

It used to be different. A few months ago I changed the priority of if-then-else to make it more compatible with Scala expressions. E.g.,

if (test) a else b+c

would in Scala be parsed as

if (test) a else (b+c)

but SubScript tookit as

(if (test) a else b) + c

So a few months ago that has been changed. SubScript's whitespace separator has even a higher priority than n-ary operators such as "+". A space and a tab are whitespace, but also a newline. This is somewhat confusing, as this issue report shows. Maybe it is even unnecessary. Scala newlines may become inferred semicolons. It could be a good idea to do the same for SubScript.

I think if we do not see strange surprises in the current code, that would result from treating spaces and newlines differently, then we should IMO make this change.

AndreVanDelft commented 9 years ago

I have implemented the changes that I announced in the previous message. Now the semicolon inference and priorities of semicolons, if-then-else and 'normal' expressions have priorities that are much similar to those of Scala.

There are two main differences:

p =;+ a b
       c d
       e f

is shorthand for

p = a b
   +  c d
   +  e f
p =+ a b c d e f

is shorthand for

p = a + b + c + d + e + f

In plain Scala white space may introduce infix method calls and their parameters, as in 1 to 10.