Sunday, March 26, 2006

Scala: Everything is an Object!

The main force behind design of Scala is unification of the object-oriented and functional paradigms. Every function in Scala is a value, every value is an object - hence every function in Scala is an object. Hence everything is an object in Scala.

The unification of OO and functional paradigms in Scala is managed by an advanced static type system -

  • Scala supports algebraic data types, that can be decomposed for pattern matching as found in functional languages.

  • Scala also offers class hierarchy based static typing of object oriented languages


Thus Scala can express both closed and extensible data types, and also provides a convenient way to exploit run-time type information in cases where static typing is too restrictive.

Numbers are Objects

Java distinguishes numeric types from objects - Scala does not.
e.g. In the following expression

1 + 2 * 3 / x

Scala sees it as

1.+(2.*(3./(x)))

It treats every number as an object and every operator as a method invoked on that object. Operators and identifiers are never distinguished - they can either be a sequence of letters and digits which begins with a letter or a sequence of special characters, such as “+”, “*”, or “:”. A binary operation 1 + 2 is interpreted as 1.+(2), which is interpreted as invocation of the method "+" on integer value 1.

Similarly the concatenation operator "::" of a List follows the same principle -

val nums = 1 :: 2 :: 3 :: 4 :: Nil // adopted from [Scala By Example]

is equivalent to

val nums = 1.::(2.::(3.::(4.::(Nil))))

Functions are Objects

Since Scala supports functional programming, functions are treated as first class objects in Scala. Functions can be passed as arguments to other functions (Higher Order Functions), they can be used as values as well. Let us look at the anatomy of the sort function from [Scala By Example].

def sort(xs: List[int]): List[int] =
    if (xs.length <= 1) xs
    else {
        val pivot = xs(xs.length / 2);
        sort(xs.filter(x => x < pivot))
          ::: xs.filter(x => x == pivot)
          ::: sort(xs.filter(x => x > pivot))
    }


  • The function is an expression - hence there is no explicit "return" statement. The function evaluates to a value which is a List of int.

  • According to the usual quicksort algorithm, the sort works by partitioning the list into three sublists and then concatenating the sorted sublists by recursive calls around the pivot. The three sublists are concatenated using the list-concatenation operator ":::".

  • The most interesting part happens within the calls to filter. The filter method of the List accepts a Predicate and returns a list of elements for which the predicate evaluates to true. It has the signature

        def filter(p: t => boolean): List[t]


    Here, t => boolean is the type of functions that take an element of type t and return a boolean. Functions like filter that take another function as argument or return one as result are called higher-order functions.

    Experienced Java programmers must now be wondering about the black magic going on behind the predicate implementation. Actually it is bread-and-butter stuff for functional programming - Closures at work! The argument to filter is an anonymous function (a function defined without a name), which is created on the fly and has access to the enclosing lexical scope, through which it gets the variable pivot. The argument to the first filter call, x => x <= pivot represents the function that maps its parameter x to the boolean value x <= pivot. The function returns true if x is less than or equal to the pivot, false otherwise. Also, we have an implicit iteration going on here within filter, where each value fetched is put into x. The Scala compiler is smart enough to infer the type of x from the context, the user does not have to provide it explicitly.

    Try implementing the same in Java or C++ - you won't be disappointed that you have come this far in this entry!


  • Closures in Scala Stand Out

    Closures are offered by all functional/hybrid languages, but the one from Scala implements one of the best approaches for lazy evaluation of expressions.
    Let us look at an example from the Scala world -

    object TargetTest1 extends Application {
      def whileLoop(cond: => Boolean)(body: => Unit): Unit =
        if (cond) {
          body
          whileLoop(cond)(body)
        }
      var i = 10
      whileLoop (i > 0) {
        Console.println(i)
        i = i - 1
      }
    }


    In the above example, when the method whileLoop is applied, the actual arguments are NOT evaluated immediately. Instead they are encapsulated within nullary functions and passed as the corresponding actual parameters - the classic call-by-name evaluation. Scala's automatic closures allow building new control structures avoiding the need for the caller to explicitly state that an expression must be evaluated lazily.

    Let me end this post with a comment from Gilad Bracha on the strengths of Scala ..
    Scala is one of the nicest and most powerful languages around, and runs on a JVM as well. It has a lot of really nice features - purely object oriented, closures, mixins, a powerful type system, a powerful notion of modularity, and it interoperates well with the Java platform.

    The next post on Scala will talk about the Class abstraction and two of its composition mechanisms - Mixins and Traits.