Archive for August, 2008

Object-Functional Programming is Here

Monday, August 18th, 2008

In Computer Science, we have all been educated to recognize the terms Object-Oriented, Functional-Programming, Logic-Programming, etc.

It is time for a new term to enter our vocabulary: Object-Functional Programming. It represents the fusion of object-oriented and functional-programming cultures and it happening right now, with its finest representative, Scala.

I have been playing around with the term and concept for quite some time now (e.g. see here, where I mention similar ideas and try to track them down in time). I will certainly have to say more in the near future, so keep in touch!

Enter reflection, meet type unsoundness

Sunday, August 17th, 2008

The theoretically-inclined may judge if the subject correctly characterizes the situation I am about to describe.

At some point while programming a library (in Scala, of course), I thought it would be a nice idea to abstract over some compiler-powered magic regarding the handling of for-comprehensions, and in particular those compiled to foreach() calls. So, I came up with this:


type ForEach[T] = {
  def foreach(f: T => Unit): Unit
}

Now, let’s define a generic function:


def foreachWrapper[T](container: ForEach[T], f: T => Unit) {
  for(value < - container)
    f(value)
}

So, any type adhering to the ForEach structural contract can be passed to foreachWrapper. Of course this is a trivial function, but suffices for the purpose of this post.

Now, we know that Lists and Arrays are specially handled by the compiler when appearing in a for(v <- c) construct, and we deserve the right to believe that this:


foreachWrapper(List(1, 2))

and this:


foreachWrapper(Array(1, 2))

will type-check. And indeed they do, as expected. So our program is correct.

But if we try to run it (see the complete code at the bottom of this post), we get an exception:


java.lang.NoSuchMethodException: [I.foreach(scala.Function1)

Hmmmm.... What the Hack??? The situation is blurred (note that [I is the class of an integer array in Java). But wait a minute!

We know that structural types, implementation-wise, interfere with reflection, and there is where the exception comes from. And this is all because Scala does its best to handle arrays in the most balanced way.. Array(1, 2) is compiled to a respective Java array but Java arrays do not define a foreach method!

As expected, If we force Scala to box the array, using this trick:


def boxMe[T](me: Array[T]): Array[T] = me

then there is no problem at all…

C’est la vie. You get something, you lose something else…

The complete code follows:


object foreach {
  type ForEach[T] = {
    def foreach(f: T => Unit): Unit
  }

  def foreachWrapper[T](container: ForEach[T], f: T => Unit) {
    for(value <- container)
      f(value)
  }

  def boxMe[T](me: Array[T]): Array[T] = me

  def rollIt[T](container: ForEach[T]) {
    println("-- Iterating over: " + container.getClass.getName)
    foreachWrapper(container, println)
  }

  def main(args: Array[String]) {
    val intList = List(1, 2)
    val intArray = Array(1, 2)

    rollIt(intList)
    rollIt(boxMe(intArray))
    rollIt(intArray)  // Exception!
  }
}