Sunday, February 03, 2008

Scala tutorial

On a cold gray sunday afternoon, I went through the tutorial for the Scala programming language (by a group in Switzerland called LAMP). There was an exercise straight out of SICP about evaluating simple algebraic expressions. Here's what I came up with. It may be far from optimal, but seems to work for at least the one test case.

abstract class Tree
case class Sum(l: Tree, r: Tree) extends Tree
case class Var(n: String) extends Tree
case class Const(v: int) extends Tree

object Expressions {
type Environment = String => int

def eval(t: Tree, env: Environment): int = t match {
  case Sum(l, r) => eval(l, env) + eval(r, env)
  case Var(n) => env(n)
  case Const(v) => v
}

def derive(t: Tree, v: String): Tree = t match {
  case Sum(l, r) => Sum(derive(l, v), derive(r, v))
  case Var(n) if (v == n) => Const(1)
  case _ => Const(0)
}

// there's probably a more functional way to do this
def simplify(t: Tree): Tree = t match {
  case Sum(l, r) =>
    val sl: Tree = simplify(l)
    val sr: Tree = simplify(r)
    sl match {
      case Const(lv) => sr match {
        case Const(rv) => Const(lv + rv)
        case _ =>
          if (lv==0) sr
        else Sum(sl,sr)
      }
      case _ => sr match {
        case Const(rv) if (rv==0) => sl
        case _ => Sum(sl,sr)
      }
    }
  case Var(n) => Var(n)
  case Const(v) => Const(v)
}

def toString(t: Tree): String = t match {
  case Sum(l, r) => "(" + toString(l) + " + " + 
                    toString(r) + ")"
  case Var(n) => n
  case Const(v) => v.toString()
}

def main(args: Array[String]) {
  val exp: Tree = Sum(
                    Sum(Var("x"),Var("x")),
                    Sum(Const(7),Var("y")))
  val env: Environment = { case "x" => 5 case "y" => 7 }
  println("Expression: " + toString(exp))
  println("Evaluation with x=5, y=7: " + eval(exp, env))
  println("Derivative relative to x: " + 
          toString(derive(exp, "x")) + " = " +
          toString(simplify(derive(exp, "x"))))
  println("Derivative relative to y: " +
          toString(derive(exp, "y")) + " = " +  
          toString(simplify(derive(exp, "y"))))

}

The subclasses of Tree define the nodes of a parse tree for simple expressions like:

((x + x) + (7 + y))

The program demonstrates Scala's pattern matching capabilities, defining methods that perform operations on trees: evaluate, take derivatives, and print. Pattern matching is a feature borrowed from the ML family of languages. You might think of them as case statements on steroids. Sometimes they can concisely replace polymorphism. Here, they play the role of the visitor pattern.

The visitor pattern makes it easy to add new operations on all members of an inheritance hierarchy in a modular way. (Modular meaning the operation is encapsulated). The cost is that adding a new member to the inheritance hierarchy requires modification of all existing operations. The cost and benefit of pattern matching statements is the same.

More Scala Resources:

Friday, February 01, 2008

Things I'd like to be able to do in Eclipse

  • Right-click on an interface in the Package Explorer and say "Implement" and get a new class with stub implementations of all the methods in the interface.
  • Similarly, right-click on a class or interface and say "Extend".
  • Further, you could right-click on a class or interface and say "Generate Proxy" or "Wrap" and get a new class that wraps an instance of the existing artifact and then opens the "Generate Delegate Methods" dialog.

I know there are ways to do all these things that only take a few steps, but they're fundamental tasks that deserve a one-step command. "Implement this interface" is a lot closer to how I think than "Create a class that implements interface Foo".

  • Expand-all packages (but don't expand into java files) in the Package Explorer.

Wednesday, January 30, 2008

Friday, January 25, 2008

Java Packages and Dependency Management

I used to think Java's packages were a great thing. They solved the problem of naming conflicts and enforce a consistent system of organizing source code on disk for everything written in Java. That view came from working on some C/C++ codebases where boundaries of name-spaces were haphazard or nonexistant and the conceptual organization of the source bore no relation to the location in the file system of the various modules that made up the program. Tracing an execution path through the code was next to impossible and the build process a nightmare.

I had a friend, an experienced C++ developer who said he always felt straight-jacketed by Java packages. He didn't want to be forced to organize his files in the same way he organized his packages. I never understood why anyone would want the freedom to create the type of disaster I had seem before. But there's a part of the picture I was missing. Packages also imply something about dependencies.

Good guidelines on packaging are remarkably hard to come by. But, at minimum, a well designed package structure will minimize dependencies between packages and avoid circular dependencies. I've come to follow other rules of thumb about inter-package dependencies. Everyone can depend on a util package. But a util package should have no dependencies inside the project. Domain model classes should be defined abstractly and be free of outside dependencies.

Inversion of control is when code at a lower level of abstraction depends on code at a higher level of abstraction. The domain model is defined at a high level, with little or no implementation detail. In fact, much of my domain models are just interfaces. Lower level packages do the grunt work with specializations of the domain model artifacts.

Recently, I worked on a project with a Swing UI, which I hadn't done in years. I created a ui package to hold all the Swing related kerfuffle. I started noticing that I had a lot of actions. These little 20 line subclasses of AbstractAction define the event handlers used by controls throughout the UI and seem to multiply like rabbits. Mixed in with the rest of the UI classes, classes that formed the windows, panels, dialogs, and other on-screen widgetry of my app, the actions were hard to find and just cluttered up the place. I wanted, for strictly organization reasons, to move them out of the way.

Of course, the actions depend on the UI widgets they invoke and the UI widgets depend on the actions. So, if I put my actions in a separate package, I'd have a big ugly circular dependency staring me right in the face. I go sick of looking at the action classes, so I did it anyway. Where dependencies and name-spaces are concerned, they're all in one conceptual unit. But on disk, and therefore necessarily in the package hierarchy, they're in two different places.

Since becoming more aware of the role dependencies play in packaging, I've notice more little conflicts of interest like this. I still prefer the enforced file system structure of packages to total chaos, but I now recognize my friend's point.

It would be an interesting extension to the language to be able to explicitly declare that package X was allowed to depend on packages Y, Z, and util. Any other dependency could generate a compiler warning. There are static code analyzers that will do just that. (JDepends for example.) It would be even better if the IDE was aware of such things and could issue a warning as you added a suspicious dependency.

Wednesday, January 23, 2008

Visual computing platforms

processing: an open source programming language and environment for people who want to program images, animation, and interactions. Processing was initiated by Ben Fry and Casey Reas. vvvv: a toolkit for real time video synthesis.
prefuse: software tools for data visualization.
AIR: programmatically access Adobe's Flash engine + webkit

Link to Manageability blog

Manageability blog has a blurb about the demise of the Chandler project asking whether Python was to blame. From there, there's some interesting looking links about the architecture of Eclipse. Actually, Ted Neward's comments were better than the original post.

Thursday, January 17, 2008

Java Integer.decode broken

If you're aware of two's compliment representation of integers, you can probably guess the output of the following line of Java:

System.out.println(Integer.toHexString(-1));

Sure enough, you get this:

ffffffff

Knowing that, what do you think the result of this line might be?

System.out.println(Integer.decode("0xffffffff"));

Would you believe NumberFormatException: For input string: "ffffffff"? The reason is that decode works on signed values. Ugly with a capital Ug. Decode works as expected on hexadecimal values in which the most significant bit is clear. But here, that high bit is set. The decode function expects a negative hex value where ever you'd use a negative decimal value.

Now, what would be a proper punishment for the kind of protohuman homunculus who would use a sign with a hexadecimal number? Fifty lashes with a wet noodle for the addled mind that thought this was a good idea:

Integer.toHexString(Integer.decode("-0x1"));
ffffffff

Most sane programmers find this highly annoying. There's a bug dated in 1999, (and several dupes) in the Java bug database for this, and its counterpart bug in Long. What an embarrassment.

One work-around (for integers) is to use a Long when you expect a hex number with the sign bit set.

int thisIsTotallyWeak = Long.decode("0xffffffff").intValue();