Thursday, June 26, 2008

On Scala Language - First Impressions

A couple of days ago I started playing with the Scala programming language (http://www.scala-lang.org). I decided to document my experience with this language. I will be talking in Java terms, so if you see me referring to, for example, something 'static', think of Java's definition of 'static'.

Several things immediately caught my attention. The language is concise, type-safe, lacks a keyword for declaring 'static' and 'final' members, lacks 'throws' keyword (i.e. all exceptions are runtime), fully interoperates with Java and Java libraries, contains elements of a functional language.

Certain things pop up in a Java developer's mind right away after hearing the above (I tested it on some of my Java-savvy friends and on myself, of course):
  • But how do I declare static variables and constants?
  • Functional elements, ha. Are we messing with the 'return' statement again? If there's no return statement I don't wanna hear about it. (Then they close their ears and go: "Bla-bla-bla-bla...")
  • Interoperates with Java as in JNI or somethin'?
  • No checked exceptions? How come?
I will try to answer these questions right away as it is almost impossible to move on. Java developers have heard a lot about attempts to make a language concise, expressive, and so on. All was at the expense of type-safety (Python, Ruby, Groovy, etc). So their scepticism just keeps growing.

This example answers all the questions:


package scalatest

import java.io.File

object HelloWorld {

def main(args : Array[String]) {
println(message0)
println(message1)
println(message2)
println(message3)

this.message3 = "hehe"
println(message3)

/*
This won't compile
message2 = "hehe"
*/

val f = new File(".")
println(f.getAbsolutePath)

if (false) {
throw new java.io.IOException("Just a test")
}

println("Semi-colons at the end of an expression are optional too");
println("But you can" +
" still do multi-line "
+ "expressions")

val a =
"""This might be useful sometimes too.
You can embed Python-style multiline strings like this one.
Looks ugly at first, but I can see myself getting used to it.
I don't think I will use it a lot though"""

println (a)
}

/**
* A method with a return statement
*/
def message0 : String = {
if (new Random().nextBoolean()) {
return "Hello, World!"
} else {
return "Goodbye, World!"
}
}

/**
* A method without a return statement
*/
def message1 : String = {
println("This is definitely a multi-line method")
println("Looks like return statements are optional")
if (new Random().nextBoolean()) {
// Hopefully future IDEs will mark the returned expressions automatically
"Hello, World!"
} else {
// It's not that hard
"Goodbye, World!"
}
}

/**
* A constant (i.e. equivalent of Java final keyword)
*/
val message2 : String = "abc"

/**
* Not a constant, just a field
*/
var message3 : String = "def"

}


Static Variables: Scala solves Java's problem with static members by dedicating a special construct for this purpose. It's called 'object'. 'object' is a class-singleton. In this example HelloWorld is an object, so everything in it is automatically static. This is good, because when you allow static members in your regular classes (as Java does) you run into problems with polymorphism. Scala doesn't, hurray!

Constants: Scala has a very elegant solution for constants. Constants are simply values (the keyword is 'val'). Java uses an oxymoron syntax declaring a constant as variable that doesn't change. However, we are used to it by now, so we don't look at it this way anymore, but Scala does remove a lot of code bloat by calling constants what they really are:



val HELLO = "World!"


VS


public static final String HELLO = "World!";


The 'return' statement: Scala does mess with the 'return' statement. The good news is that you can still use it. It is optional. Plus, because the language is type-safe the compiler won't allow you to return just anything. Plus, there is a good chance that an intelligent syntax highlighter will mark the returning expression.

Interoperability with Java: Looks good. I checked it by using a Java class in Scala code (see the example). The claim is that you can also extend Java classes and implement Java interfaces and use Scala classes in your Java classes. This was a very practical decision. Struts application in Scala, anyone?

Checked exceptions: Scala does not require you to catch checked exceptions, but you can still use them (see the example). There is no mechanism to declare thrown exceptions either. Checked exceptions is still a debate (http://www.mindview.net/Etc/Discussions/CheckedExceptions). I don't like them. Only Java has them. The rest of the world lives happily without them. I try to avoid them as much as I can. Documenting thrown exception is one thing. Fixing bugs because of swallowed exceptions or interpreting methods throwing Throwable is another. All of this is created by the psychological phenomena created by checked exceptions. So I am glad that Scala does not have checked exceptions (I can already see 50% of my audience leaving this web-site :).

So, Scala seems to have gotten right the things that I usually complain about in Java, and they did not have to sacrifice type-safety. Let's see if they've got everything else right...