nosewheelie

Technology, mountain biking, politics & music.

Archive for January, 2008

Functional programming for the object oriented

with one comment

IBM has now joined the hype behind Scala with a series of articles by Ted Neward (to be fair, he’s been around Scala for a while now).

Java programming, and object-orientation, was the first love for many programmers, and we treat it with the same respect and outright adoration I gave to Bindi. Some developers will tell you that Java programming rescued them from the hellfire-and-brimstone pits of memory-management and C++. Others will say that Java programming elevated them out of the depths of procedural despair. There are even developers for whom object-oriented programming in Java code simply is “the way we’ve always done things.” (And hey, if it worked for my daddy, and his daddy before him!)

Time ultimately overcomes all first loves, however, and there comes a time to move on. The feelings have changed and the actors in the story have matured (and hopefully learned a few new jokes). But more importantly, the world around us has changed. Many Java developers are realizing that much as we love Java programming, it’s time to catch up to the new opportunities in our development landscape and see what we can make of them.

Source: The busy Java developer’s guide to Scala: Functional programming for the object oriented.

Written by Tom Adams

January 24th, 2008 at 8:09 am

Posted in Scala

Obi source moved to Google Code

without comments

I’ve just moved the Obi code from the internal Workingmouse repository to Google Code. Behold the shiny new home of Obi. Still not much to see, you’ll need to grab the source.

Written by Tom Adams

January 23rd, 2008 at 3:56 pm

Posted in Obi,Scala

Path composition in Obi

without comments

Over the last few days I’ve been progressing steadily with Obi, my Scala-based build tool. I’m starting at the bottom level, building some low level primitives that can then be combined into higher level layers (examples at the end of this post).

Here’s the first simple example, it represents a path to a file on the filesystem.

import org.obi.io.file.FilePath._

// Create a FilePath
val p1 = filepath("/foo/bar.jar")
val p2 = path("/foo/bar.jar")

// Implicit conversion from String to FilePath
val p3: FilePath = "/foo/bar.jar"

// Implicit conversion from FilePath to String
val p4: String = path("/foo/bar.jar")
 

FilePaths can also be combined to form classpaths (I’m working on javac). Here’s some examples of the way you can create classpaths, each of the these will give the classpath string /foo/bar.jar:/foo/baz.jar (on a *nix box). All are syntactically valid Scala, syntax requests/suggestions are welcome, these are some that I came up with, that’ll probably change once it’s used inline in the compilation task.

import org.obi.attr.ClassPath._
import org.obi.io.file.FilePath._

val cp1 = classpath("/foo/bar.jar", "/foo/baz.jar")
val cp2 = classpath(List("/foo/bar.jar", "/foo/baz.jar"))
val cp3 = classpath < < "/foo/bar.jar" << "/foo/baz.jar"
val cp4 = classpath << List("/foo/bar.jar", "/foo/baz.jar")
val cp5 = "/foo/bar.jar" <<: classpath("/foo/baz.jar")
val cp6 = List("/foo/bar.jar", "/foo/baz.jar") <<: classpath
val cp7 = "/foo/bar.jar" << classpath << "/foo/baz.jar"
val cp8 = classpath("/foo/bar.jar") << classpath("/foo/baz.jar")
val cp9 = classpath("/foo/bar.jar") ::: classpath("/foo/baz.jar")
val cp10 = classpath("/foo/bar.jar") + classpath("/foo/baz.jar")
val cp11 = classpath("/foo/bar.jar") + "/foo/baz.jar"
val cp12 = "/foo/bar.jar" :: classpath("/foo/baz.jar")
val cps: String = classpath << "/foo/bar.jar" << "/foo/baz.jar"

With these kind of primitives, it'd be pretty easy to create abstractions such as "library" which would enable a feature such as Maven's dependency management using a syntax similar to buildr's. Here's a simple example of what's currently implemented, syntax can be cleaned up.

val log4j = path("log4j.jar")
val cglib = path("cglib.jar")
val commons_logging = path("commons-logging.jar") < <: log4j
val ehcache = commons_logging << "ehcache.jar"
val hibernate = ehcache + commons_logging + cglib

There's no way to "resolve" dependencies as yet (and won't be for a while) and you get duplicates in the path. But, this would open up things such as (I've no idea if this is valid syntax, I doubt it is):

val hibernate = library(
        dependencies |= ehcache + commons_logging + cglib,
        version "3.2.5.ga")

All in all I think the syntax is quite readable and flexible, it’s also strongly typed. Writing these kinds of DSLs has proved very easy using Scala, I’m quite impressed.

Written by Tom Adams

January 22nd, 2008 at 8:58 pm

Posted in Obi,Scala

Scala varags handling

with 2 comments

Mainly for my future reference, a quick overview of how Scala appears to handle varargs. The Scala book doesn’t offer an explanation currently so this is all derived through experiments using Scala 2.6.1.

To make a method accept a variable number of arguments, it is defined as follows.

scala> def foo(s: String*) { println(s) }
foo: (String*)Unit

Like Java, Scala requires the vararg to be the last parameter to the function. Once in your method, the parameter is of type Array[String] (more generally Array[A] where A is a type parameter).

scala> def foo(s: String) { println(s) }
foo: (String)Unit

scala> foo("hello")
hello

scala> def foo(s: String*) { println(s) }
foo: (String*)Unit

scala> foo("hello", "world")
Array(hello, world)

scala> def foo(s: String*, t: Int) { println(s) }
:4: error: *-parameter must come last
       def foo(s: String*, t: Int) { println(s) }
               ^

Unlike Java 1.5, you must explicitly declare your functions to accept variable arguments, you can not declare a parameter to be an Array[A] and have the runtime perform an automatic conversion for you (I believe this may have something to do with Java 13/1.4 compatibility). So the following is not equivalent to the above and will not compile:

scala> def foo(s: Array[String]) { println(s) }
foo: (Array[String])Unit

scala> foo("hello", "world")
:6: error: wrong number of arguments for method foo: (Array[String])Unit
       foo("hello", "world")
       ^

Likewise, you can not declare something to take a varargs parameter and call it as if it’s an array (as you can in Java):

scala> def foo(s: String*) { println(s) }
foo: (String*)Unit

scala> foo(Array("hello", "world"))
:6: error: no type parameters for method apply: (A*)Array[A] in object Array exist so that it can be applied to arguments (java.lang.String,java.lang.String)
 --- because ---
result type Array[A] is incompatible with expected type String
       foo(Array("hello", "world"))
           ^

There’s also some odd rules around overloading of functions, due to erasure:

scala> object Foo { def foo(ss: String*) = println(ss); def foo(is: Int*) = println(is) }
:4: error: double definition:
method foo:(Int*)Unit and
method foo:(String*)Unit at line 4
have same type after erasure: (Seq)Unit
       object Foo { def foo(ss: String*) = println(ss); def foo(is: Int*) = println(is) }

The variable argument gets the type Seq[A] (the actual underlying runtime type is Array[A]), and owing to the wonderful properties of erasure, both these methods have the same signature.

Written by Tom Adams

January 22nd, 2008 at 12:04 pm

Posted in Scala

Scala for Java refuges

with one comment

Daniel Spiewak has a series of posts (1 through 3 currently) on introducing Scala to Java developers.

Written by Tom Adams

January 22nd, 2008 at 8:08 am

Posted in Scala

Anonymous commenting switched off

with 3 comments

In an effort to reduce the amount of spam I have to deal with via this blog (roughly 3000 per week, of which 50 odd get through the Akismet filter), I’ve turned off anonymous posting. You will now need to enter a name and address to post comments. Apologies if this affects anyone adversely.

Written by Tom Adams

January 18th, 2008 at 9:50 am

Posted in Blog

Obi is born

with 5 comments

In an effort to learn Scala I’ve been playing around with creating a build tool, called Obi. This is nothing more than me looking for a nice way to learn Scala, but after a couple of days of thinking it looks quite doable.

Obi has three goals; 1) allow me to learn Scala, 2) provide a nice DSL that is expressive and allows use of Scala APIs and idioms and 3) provide the type safety of the Scala language, e.g. a javac task will not compile if you do not pass it a source file.

Here’s an example of the current syntax we’re playing with, this doesn’t actually do anything as yet, but does compile (well, most of it compiles). Each call is pure (side effect free), you need to apply the ! to actually execute the tasks.

import SrcDir._
import Javac._
import AntJavac._

// Two compile targets, Java code and Scala code
val jc = javac(srcdir("src/main/java")).srcfiles(
        List("Foo.java", "Bar.java"))
val sc = scalac.srcdir("src/main/scala").srcfiles(
        List("Foo.scala", "Bar.scala"))

// Equivalent of an Ant "target", Java compile is performed
// before Scala compile, both tasks are executed when called.
def compile {
    !jc
    !sc
}

// Compile Foo.java & Bar.java in src/main/java
!javac(srcdir("src/main/java")).srcfiles(
        List("Foo.java", "Bar.java"))

// Create a compile for Foo.java & Bar.java in src/main.java
List("Foo.java", "Bar.java") >>: javac(srcdir("src/main/java"))

// Create a compile for all files in src/main.java
Dir("src/main/scala")  >>: scala(srcdir("src/main/scala"))

// compile all Scala source files in an "obi" directory
val scalaCompile = Dir("src/main/scala")
        .filter(_.matches("""obi.*\.scala$""")) >>: scalac
!scalaCompile

For those that want to look at other Scala tools, it looks like the only tool available currently is SAnt, Maven and Ant.

If you are interested, Obi is not named after Obi-Wan Kenobi, but after Obi Obi Creek on the Sunshine Coast of Queensland (where I’m doing a throughwalk later this year).

Written by Tom Adams

January 17th, 2008 at 4:44 pm

Posted in Obi,Scala

Bring bad design to justice

without comments

Written by Tom Adams

January 17th, 2008 at 10:31 am

Posted in Design

scala.Option Cheat Sheet

without comments

Tony has a nice post on using Scala’s Option type:

Many people who are coming in to Scala first encounter the Option type, which may be thought of (among other things) as a type-safe null. They also encounter pattern matching as both a new and (relatively) powerful concept, but also one that is easy to understand. This leads to quite a lot of use of pattern matching and often excessively so in what I have observed.

Particularly with a type as trivial as Option, it is almost always possible to do away with pattern matching by using a higher-order function. Use of this function is typically preferred over pattern matching as tighter code.

Source: scala.Option Cheat Sheet.

Written by Tom Adams

January 17th, 2008 at 10:23 am

Posted in Scala

Refuse The Terror

with 2 comments

Via Bruce Schneier comes Refuse the terror, very American focused, but good none the less, all I can say is I’m very glad the our previous Government was voted out of office.

See also Downsize DC, a group that appears to have similar aims of reducing the fear.

Written by Tom Adams

January 17th, 2008 at 9:00 am

Posted in Politics,World