« Quest for GloryMiscellaneous Links »

Final Scala to Java comparison

02/11/07

Permalink 09:39:54 am, 347 words
Categories: Code

Final Scala to Java comparison

Here is the final comparison of the Scala port of Heiberg's Java code. As always, comparing a port to the original is not quite fair because of accumulated cruft that gets thrown out.

The Java code was high quality, mostly idiomatic Java 1.1 code that was updated to take advantage of generics and for-each syntax. The main oddity was the use of public fields, which was convenient but made refactoring harder. Scala has no public fields (though it can use those compiled by Java), so that part of the port was annoying. There was a Pascal accent to the code, especially the avoidance of return/continue/break as well as nested if instead of && (due to Pascal's broken and semantics).

My Scala code improved greatly as I learned it while porting. However, there is likely still a strong Python and OCaml flavour to the code. In particular, I think my naming conventions do not match Scala's well. The lack of documentation on the language itself is a factor; there are a few good case studies, but if you stray from these you are on your own, especially for recent feature changes which seem to happen frequently. Interop with Java has almost no documention, partly because there isn't much there; however since both languages compile to the same bytecode, there isn't any magic required to write your own interop layer. Another area that is weak is the documentation of traits, which are equivalent to Ruby modules and close to Java's interfaces. Fortunately I was able to find some online discussion of how to make a Java class implement a Scala trait.

units Scala Java Ratio
bytes 55874 88036 63.47%
words 6405 10160 63.04%
lines 1456 2859 50.93%

Compared to the previous analysis, the numbers have all dropped by hair; two percent each for words and lines and one percent for bytes. My bias for short, squat files still shows: Scala's word count is 2/3 of Java's but the line count is 1/2. Some of the longer lines come from my bias and some are an unavoidable consequence of functional programming. I promise I didn't stack ending braces Scheme-style! ( } } })

7 comments

Comment from: Ricky Clarkson [Visitor] · http://cime.net/~ricky/
Scala does have public fields.

case class X(x:Int)

X(5).x gives 5
09/11/07 @ 06:52
Comment from: Ricky Clarkson [Visitor] · http://cime.net/~ricky/
I've since been corrected. Scala appears to have public fields, but they're done with a generated accessor and mutator. Either way, they look like Java's public fields.
09/11/07 @ 07:28
Comment from: sandersn [Member]
Yes, I was painfully aware of the distinction because of trying to use fields in both Scala and Java. Unfortunately, I think that a field with accessor and mutator in Scala doesn't provide much more protection than a public field in Java.

I didn't know that you could define and use case classes like that, though. I think the documentation only shows how to extract the fields by pattern matching. Maybe not.
09/11/07 @ 08:07
Comment from: Ricky Clarkson [Visitor] · http://cime.net/~ricky/
I've been learning by using the documentation, and messing around, so I'd guess the docs show what I did. ;)

Even non-case classes support that, for example:

class X(val x: Int)

new X(5).x gives 5

Also:

class X { val x=5 }

new X().x gives 5
09/11/07 @ 08:21
Comment from: Chas Emerick [Visitor] · http://blog.snowtide.com
> Unfortunately, I think that a field with
> accessor and mutator in Scala doesn't
> provide much more protection than a public
> field in Java.

It certainly does -- that approach allows you to revise how to calculate the value of a field without changing the interface of the class. i.e., you can change the X class that Ricky specified to this without breaking client code:

class X (private val y) {
def x = y + 2
}
09/11/07 @ 09:55
Comment from: sandersn [Member]
Oh, yes, you're right. I tend to forget these things, coming from Python/Caml. I was thinking of the case in which you have
class X () {
val a = new scala.collection.mutable.ArrayBuffer[Int]
}

But I guess there is still some advantage even if other code says
x.a += 100
Because you can at least change it to a def to insert your own code to control the ArrayBuffer that is actually returned.

Hmm...this makes me wonder about type inference in Scala. Does
val a = new ArrayBuffer[Int]
give your class a public interface of ArrayBuffer[Int] or Seq[Int]? It looks like the former.
Hmf. Nominal type systems strike again.
09/11/07 @ 10:19
Comment from: David MacIver [Visitor] · http://unenterprise.blogspot.com
Yes. If you want something a more general type you can write

val a : Seq[Int] = new ArrayBuffer[Int]

or for that matter

val a = new ArrayBuffer[Int] : Seq[Int]
09/11/07 @ 11:49

Comments are closed for this post.

powered by b2evolution free blog software