Things I do not like in Scala

As you can guess, I'm a fan of the Scala programming language. Nevertheless, unlike some Ruby evangelists, I can say that there is something in my favourite programming language that I don't like. Here are some examples.

Semicolon inference

The first one is about how Scala considers the end of statements.
Let's take a look at this code.

 
package bad   
 
object BadScala {   
 
  def subtractVersion1(a: Int, b: Int) = {
    a -
    b
  }   
 
  def subtractVersion2(a: Int, b: Int) = {
    a
    - b
  }   
 
  def main(args : Array[String]) : Unit = {
    println(subtractVersion1(10, 2))
    println(subtractVersion2(10, 2))
  }
}

The output of this program is

8
-2

Unlike Java, Scala does not require semicolons to close a statement. In Programming in Scala we can read

A line ending is treated as a semicolon unless one of the following conditions is true:
1. The line in question ends in a word that would not be legal as the end of a statement, such as a period or an infix operator.
2. The next line begins with a word that cannot start a statement.
3. The line ends while inside parentheses (...) or brackets [...], because these cannot contain multiple statements anyway.

So in method subtractVersion1 there is only one statements that spans two lines, giving a - b as return value. In subtractVersion2 the compiler infers a semicolon at the end of the first line, so the result value is -b.

The missing equal sign

Now let's see how forgetting an equal sign could be dangerous.

 
package hello   
 
object BadScala2 {   
 
  def myFavouriteLanguage1() = {
    "Scala"
  }   
 
  def myFavouriteLanguage2() {
    "Ruby"
  }   
 
  def main(args : Array[String]) : Unit = {
    println(myFavouriteLanguage1)
    println(myFavouriteLanguage2)
  }
}

This program gives as output:

Scala
()


(It seems that there is no way to make me say that Ruby is my favourite language ;-) )

The only difference between the above two methods myFavouriteLanguage1 and myFavouriteLanguage2 is a missing equal sign. In Scala if a method declaration does not have an equal sign before its body, the compiler infers that the result type will be Unit (something like void in Java). So, as also the return keyword is optional (and, in fact, it's never used in idiomatic Scala), the method will not give any result, or, we should say, a result which type is Unit, and it's rendered as ().

Is Scala a bad programming language?

So is Scala a bad programming language? In my humble opinion, Scala is a really powerful programming language, the best one I have learned so far. Anyway, in it there is a trade-off between power and safeness. We should know its weakness in order to use it effectively and enjoy its power.

5 commenti

  1. Matt:

    Interesting post, it’s good to document the “standard traps” that every language end up with, even one as well-designed as Scala.

    Overall, I’m a fan of semicolon inference. The blighters really are 99% redundant, and their absence contributes to Scala having some of the feel of a dynamic language like Python or Ruby. I agree that the “gotya” you outline is rather unpleasant, but I haven’t been bitten by anything like it yet in practice. Maybe I’ve just been fortunate!

    I’m more ambivalent about Scala’s “equals-sign-vs-without” syntax for method declarations, which I’ve found rather unintuitive to learn. Still, the gotya you mention above is likely not a huge issue in practice, as I suspect the majority of the time accidentally omitting the equals will result in a compile-time type error at a call site. It’s also the sort of thing that could be readily flagged as a warning by the compiler or IDE.

  2. piggybox:

    For the 1st issue, Ruby has that one as well. Really, how can a compiler guess things like this:

    a
    -2

    is this one statement ‘a-2′ or 2 statements where ‘-2′ is the return value? We can’t tell, not to mention the poor compiler. So, next time when you break a line, break it after an operator.

  3. Justin:

    Thanks for your post. I very much agree about the semicolon inference issue. That’s a showstopper for me.

    For example, when writing tens of thousands of lines with ActionScript I was bitten by the “optional semicolon” bug many times. There are myriad ways that you can have a statement span two lines which results in bugs (sometimes very hard-to-find bugs). Having to remember to format my lines so that the line terminator could be correctly inferred is, at best, irritating. I got bit enough times that I swore i would never use a language that doesn’t terminate its statements with a semicolon[1].

    Sorry Scala, I like you and could probably learn to love you, except for the semicolon thing.

    Justin

    [1] I make an exception for Smalltalk. It uses periods to end statements. Besides, somehow ending lines with periods always seemed more natural to me than ending lines with semicolons, since that’s how I usually write English anyway. :)

  4. Klaus:

    Both issues seem somewhat problematic, agree.

    Concerning the semicolon inference issue I have specifically seen it come up in the context
    of definition of domain specific languages (DSLs). Several Scala features can be used to define
    such DSLs, specifically “Automatic Type-Dependent Closure Construction”, see :

    http://www.scala-lang.org/node/138

    The idea is very! appealing. However, there seems to be three problems
    with this approach in Scala, which I would like to see comments on.

    Problem 1 - “the eager semicolon”:
    automated inference of semicolon causes DSL constructs to be only
    partially parsed leaving the rest unparsed as a DSL construct

    Problem 2 - “the satisfied semicolon”:
    partially written (incomplete) DSL constructs are accepted

    Problem 3 - “the lazy semicolon”:
    one has to write a semilon to end a call of a method that takes () as argument,
    otherwise the Scala parser will complain about subsequent text as supurfluous arguments

    Let me illustrate the first two problems with (a slight modification
    of) the example on the page: http://www.scala-lang.org/node/138.

    // Suppose we define a loop construct as follows:
    
    object Loop {
     def loop(body: => Unit): LoopUnlessCond =
      new LoopUnlessCond(body)
    
     protected class LoopUnlessCond(body: => Unit) {
      def unless(cond: => Boolean) {
        body
        if (!cond) unless(cond)
      }
     }
    }
    
    // We can now use this as follows (use 1):
    
    import Loop._
    
    var i = 10
    loop {
     println("i = " + i)
     i -= 1
    } unless (i == 0)
    
    // The above compiles and runs correctly. So far so good.
    
    // Problem 1 : the eager semicolon.
    // The following use (use 2) gives a compile time error:
    
    i = 10
    loop {
     println("i = " + i)
     i -= 1
    }
    unless (i == 0)
    
    // This is because the unless method call is on a line for itself.
    // Scala will at the '}' infer a semicolon too early. Hence the unless
    // will no longer be a call of the method in class LoopUnlessCond.
    // This is an example of Problem 1.
    
    // Problem 2 : the satisfied semicolon.
    // An example of Problem 2 is the following, which is missing the
    // call of unless:
    
    i = 10
    loop {
     println("i = " + i)
     i -= 1
    }
    
    // this compiles correctly, but does not execute correctly. Nothing is printed.
    
    // Problem 3 : the lazy semicolon.
    // Suppose a constructs ends with a keyword, for example 'return' with
    no arguments.
    // Then one may want to write a class like:
    
    class Return {
     def return() {...}
    }
    

    and have a construct like:

    ... return
    somethingelse
    

    The compiler will look for an argument to return and will find
    ’somethingelse’ and
    will complain that return has too many arguments. So one has to insert
    a semicolon to
    make it work:

    ... return; // inserted semicolon here
    somethingelse
    

    // which is a pitty

    Any opinions about these observations?

    Regards,

    Klaus

  5. Franco Lombardo:

    Klauss,

    thanks for your very good comment, that made me write my latest post: http://www.francolombardo.net/fantom-vs-scala-semicolon-inference-and-something-more_post-98.html

Lascia un commento

You must be logged in to post a comment.