Sunday, October 16, 2011

Scala the next Java: What is the Buzz All About?

Have you ever wondered what the entire Scala buzz is all about? What you may already know:
"Scala is a general purpose programming language designed to express common programming patterns in a concise, elegant, and type-safe way. It smoothly integrates features of object-oriented and functional languages, enabling Java and other programmers to be more productive. Code sizes are typically reduced by a factor of two to three when compared to an equivalent Java application." [scala-lang]
To put it short: Scala is a hybrid object-oriented and functional programming language, runs on top of the JVM and is equipped with an expressive static type system.

So, Scala is the next Java, you say ... are you nuts? Probably yes, there's a disturbing "Scala is too complex for the average programmer" conspiracy. I'm not eager to trigger a war of the worlds, but if you are one of these folks, don't panic and try to give it a different perspective:
  • Scala is a superset of Java: It does not force you to use fancy syntax, but rather gives you the freedom to expand your arsenal gradually
  • Progress requires change: You want a statically typed language with improved expressiveness and powerful idioms, but by no means touch complexity! Oh boy ...
If you are willing to learn and want to advance, then Scala is your best bet for a long term replacement of Java. Probably, the most obvious question is: How does Scala compare to its (other) direct competitors?

Why would I choose Scala over Java?
  1. Expressiveness improves readability and reduces code size (see features below)
  2. Sophisticated type system and type inference leads to robust and compact code
  3. Extensive support for internal/external DSLs
Why would I choose Scala over Python?
  1. Static typing system catches most of your typos at compile-time
  2. Superior performance due to JVM byte-code (yes, there's PyPy, but ...)
  3. Large collection of third-party libs / Java interop (although there are countless Python bindings)
Why would I choose Scala over Haskell?
  1. Haskell's learning curve is steep (but worth it)
  2. Sometimes Haskell's purity-by-default is a PITA (io monads, no "real" imperative code)
  3. Lack of third party libraries
Now you are thinking, that's all he's got in his little arsenal? Nah!
  • Groovy:  "I can honestly say if someone had shown me the Programming Scala book by Martin Odersky, [...] back in 2003 I'd probably have never created Groovy." [James Strachan creator of Groovy]
  • Clojure: Lisp, urgh. I never liked it (yes, a very scientific statement)
  • F#: We don't want .net / mono ... do we? Although the language is nice ...
  • C++: boost gives you unlimited freedom ... and unmatched error complexity, compile times (even with pre-compiled headers), ...
Open for discussion!

To back this up with something concrete, let me give you an (incomplete) overview of some very basic syntactic features of Scala:

Here we go:
import scala.collection.mutable.HashMap

// io
println("Hello World!")      
    
// containers
var l1 = List(1,2,3) ++ List(4,5)
var l2 = (1 to 5 toList)
var l3 = List(1,2,3).filter(_ > 2)
var l4 = 1 :: 2 :: 3 :: Nil    
    
// tuples
val pair = (99, "balloons")
println(pair._1)
println(pair._2)
    
// traversal
val s = for ((k, v) <- HashMap(1 -> "a", 2 -> "b")) yield (k + v)
println(s)    
    
// factory companion
class Pojo(greeting: String, count: Int)
object Pojo { def apply(greeting: String) = new Pojo(greeting, 1) }
var p = Pojo("ops")    
    
// type (alias) definition
type T = HashMap[String, Int]
val m = new T    

// implicit conversion
class RichString(str: String) {
   def shrink = str.toCharArray.foldLeft("") { (t, c) =>
     t + (if (c.isUpperCase) c.toString else "")
   }
}
implicit def str2RichString(str: String) = new RichString(str)
println("HyperText Transfer Protocol".shrink) // HTTP
    
// operator overloading
val treasure = HashMap(1 -> "Go to island.")
treasure += 2 -> "Find big X on ground."    
    
// lambda
l1.foreach(i => println(i))
l1.foreach(println(_))    
    
// higher order functions
// def foldLeft[B](z: B)(f: (B, A) => B): B
var str = (1 to 3 toList).foldLeft("X")((str,num) => str+num)
println(str) // X123    
    
// currying
@inline def plus(a:Int) = (b:Int) => a+b
var 3 = plus(1)(2)
    
@inline def plus2(a:Int, b:Int) = a+b
val plus2Curried = Function.curried(plus2 _)
var 3 = plus2Curried(1)(2)    
    
// binding
val plus5 = plus(5)(_)
var 6 = plus5(1)
    
// multiple inheritance with order
trait Friendly { def greet() = "Hi" }
trait Dog extends Friendly { override def greet() = "Woof" }
trait Cat extends Friendly { override def greet() = "Meow" }
val dogCat = new Dog with Cat
println(dogCat.greet()) // "Meow"
    
// duck typing (upper type bound on "greet()")
def f[G <: { def greet() : String }](g:G) = println(g.greet())
f(dogCat)    
    
// pattern matching (conditional down-cast)
abstract class A
case class B(i: Int) extends A
case class C(s: String) extends A
 
val c = new C("C") match {
 case b : B => b.i
 case c : C => c.s
}
println(c) 

No comments:

Post a Comment