Odersky v. Matsumoto

| | Comments (3) | TrackBacks (0)

As some of you know, in my final quarter at Stanford I initiated and co-taught a course about the programming language Scala, entitled “Cross-Paradigm Programming with”—wait for it—“Scala.” My expertise was dwarfed by that of my co-instructors Jorge Ortiz and Julien Wetterwald, but I learned enough to give a couple of lectures. In case your appetite is whetted by the following anecdote, check out the course website, which is still operational, though I have no idea how long it will remain that way.

Anyway, as I was preparing for my lecture on implicit functions and domain-specific languages (DSLs), I came across an awesome DSL called specs, a behavior-driven design framework for Scala that improves on jMock2, a similar testing framework for PoJ (Plain ol’ Java). Since the primary advantage of specs over jMock2 is the nicer syntax supported by Scala (thanks in large part to implicit functions!), one has to assume that the author, etorreborre, values Scala for its concision.

While browsing the source of specs, however, I came across a file called Function.scala. A little background: in Scala, each function of a certain arity has a distinct type, so, for instance, there’s a type for functions that take zero arguments:

    trait Function10[+R] extends AnyRef {
      def apply(): R
    }

and a different type for functions that take four arguments:

    trait Function10[-T0, -T1, -T2, -T3, +R] extends AnyRef {
      def apply(v0: T0, v1: T1, v2: T2, v3: T3): R
    }

and so forth. By default, Scala defines types for functions of up to nine arguments. This limitation is not fundamental, however, since the user can define additional types as desired. Evidently etorrebore felt exactly this desire, for the file Function.scala defines another eleven function types, bringing the maximum arity of Scala functions up to 20.

Have a look at the file. It’s repetitive, to say the least.

Like any good programmer, etorreborre didn’t actually write out all those types by hand; instead, he wrote a program to generate them. Nothing strange about that. The code is included in a comment at the top of the file.

But wait. Wait just a second. That script is written in—gasp—Ruby? The specs library exists almost purely to exploit Scala’s expressiveness, yet, at the end of the day, its author resorts to writing one-off programs in a scripting language? What’s wrong with this picture?

Here’s the Ruby script:

    N=20
    def values_decl(n)
      (1..n).map{|i| "v#{i-1}: T#{i-1}"}.join(", ")
    end
    def Function(i) 
    "trait Function#{i}[#{(0..i-1).map{|j| "-T#{j}"}.join(", ")}, +R] 
      extends AnyRef {
      def apply(#{values_decl(i)}): R
      override def toString() = \"<function>\"
    }"
    end
    functions = (10..N).map{|i| Function(i)}.join("\n")
    puts functions

At first I was (very mildly) insulted by the choice of Ruby, but then I recognized the obvious challenge. Could the same code have been written in Scala, a strongly-typed, JVM-targeting language? I wasn’t sure, so, as any good programmer would do, I sat down and wrote it:

    object Ruby extends Application {
      def args(i: Int) = 
        (0 to i) map { j => "v"+j+": T"+j } mkString ", "
      def types(i: Int) =
        (0 to i) map("-T"+_) mkString ", "
      println((10 to 20) map { i =>
      "trait Function"+i+"["+types(i)+", +R] "+
      "  extends AnyRef {\n"+
      "  def apply("+args(i)+"): R\n"+
      "  override def toString() = \"<function>\"\n"+
      "}\n"
      } mkString "\n")
    }

Two things to notice. First, I succeeded. Second, although there is almost no difference in the lexical complexity of these two snippets of code, the second is type-safe and can be compiled to Java byte code. Not that speed really matters here, but, if it did, you’d have to appreciate the attention that Martin Odersky has paid to performance. I imagine Yukihiro Matsumoto & Co. care about performance, too, but Ruby’s speed is, well, lamentable.

Should etorreborre have used Scala instead of Ruby? Probably not. Ruby is evidently the language in which he felt most comfortable writing very small programs. My point is simply that Scala would have served just as well, and it’s always worth stepping back to examine your assumptions about which languages are suitable for which problems.

0 TrackBacks

Listed below are links to blogs that reference this entry: Odersky v. Matsumoto.

TrackBack URL for this entry: http://benjamn.com/mt-tb.cgi/28

3 Comments

Eric's blog can be found at http://etorreborre.blogspot.com/. You won't have to keep saying "s/he" :-)

I haven't looked into specs, but Scala has definitions for Functions up to arity 22 built in to the standard library (http://www.scala-lang.org/docu/files/api/scala/Function22.html) and the authors have said that if you have a compelling reason for higher arities they can add them. No idea what language they wrote their generation script in.

Thanks, James—a quick google search would have led me to Eric's blog, so I guess there's no excuse for hedging on his gender :)

Hi Ben,

Don't hesitate to ask, I can explain!

Actually, as a Java programmer I came to Scala after having played and worked with Ruby. And specs partly grew up as a way for me to learn Scala.

So at the time, it was easier and quicker for me to write this in Ruby. Since no performance nor real maintenance issue was involved it was pretty harmless.

Now, I didn't realize that those functions have been added in the standard distribution so I should remove the ones I created when using Scala 2.5.

But Functions is nothing. If you want to get really scared with some code generation, have a look at the DataTables implementation.

The usage is here: http://code.google.com/p/specs/wiki/AdvancedSpecifications

And the implementation there:

http://scala-tools.org/mvnsites/specs/1.3.0/scaladocs/index.html

That's scary! (and only time will tell if it was really worth it).

Cheers,

Eric.

Leave a comment

About this Entry

This page contains a single entry by Ben Newman published on June 21, 2008 1:26 PM.

Homeboys was the previous entry in this blog.

1006 miles in 20 days is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.

Categories

Pages

Powered by Movable Type 4.1