General musings on programming languages, and Java.

Thursday, December 11, 2008

Java Just Died (no closures in Java 7)

So it's confirmed. Despite James Gosling wanting closures, despite 3 working closure prototype compilers, despite every other JVM language supporting closures, Java 7 will not have closures.

while (true)
    print("new Runnable() { public void run() { ")
Frankly, I'm pissed off. I'm sure Java dying will kill the JVM too, ultimately.

In the meantime, there's Scala. But the Java community will probably prefer Groovy, because it has learned from Java that types are hard.

(my source: http://twitter.com/theplanetarium via Ismael Juma)

Sunday, November 23, 2008

Binary Reading and Writing Combinators for Java

Binary4J is a combinator library for reading and writing arbitrary file and stream formats. Comment on it here.

Friday, September 19, 2008

My Scala Coding Style

This was originally a posting to the scala-tools mailing list, in response to someone asking how to make the Eclipse plugin format using braces on the next line and spaces instead of tabs.

I used the braces-on-next-line rule, lining up the { to the previous line rule for years, and tabs and no spaces, for years. I was happy with it. I used an 80-character line length limit, which made coding in a text terminal easy, and tabs equivalent to 8 characters (though the actual tab width didn't really matter as I only used indentation to signify nesting depth, not to line up individual characters). My code was very structured.

If you look at my blog's very early days, you will find a post somewhere saying to avoid anonymous classes in Java. This is exactly the opposite of what I'd say now (now I'd say avoid Java :) ). It dawned on me after a while that the reason I didn't like anonymous classes was that my coding style made them a real pain in the backside to use. Specifically, if you have one anonymous class inside another with the above coding style, you end up splitting most lines of actual code.

Then I learned Lisp.

I realised that my overly structured Java code penalised me for nesting. So nesting must be bad, or the coding style must be bad.

Most human languages are highly recursive - within one sentence you can set up phrases, talk about what would happen in the future, and discuss two possible futures or even possible pasts. Only one language is known of that isn't highly recursive - the Piraha language. In Piraha the culture discourages talking about the future, or any event that you haven't seen personally, or been told about by another. A researcher who lived with them and learned their language tried telling them about Jesus (yes, there are God-botherers in linguistics too). One Piraha asked what Jesus looked like - and when the researcher said he didn't know, as Jesus lived 2,000 years ago, the Piraha wasn't interested anymore. This actually caused the researcher to start questioning his own religion, but that's a little beside the point.

I imagine that if you asked a Piraha to design a computer programming language (or a suitable analogy to one - perhaps they wouldn't be interested in computers), I imagine it would be limited to a nesting level of 2, by virtue of a 25-space tab and an 80-character line limit. And if they invented braces, I'm sure they would be lined up.

This has parallels in our society too. The more fluent amongst us can happily deal with long sentences, discussing multiple futures. The less fluent (perhaps speakers of a foreign language learning English) will generally prefer shorter sentences, discussing only the present.

In summary, pick a coding style that doesn't punish nesting, unless you want to make the language 'unnaturally' statement-orientated. I have taken this to an extreme - I use one space for indentation, and never place opening OR closing parens on their own lines. I think this is a direct result of learning Lisp, but it took a long time after learning Lisp for me to change.

Plus, silly Scala makes putting the brace on the next line fail to parse sometimes anyway.

Wednesday, September 10, 2008

Implementing the Builder pattern in Java without repeating code

When writing some Java wrappers around some CGI requests at work, I began with a normal implementation of the builder design pattern, but when I realised I was going to have to do this for about 50 CGI requests, and some of them were nested (CGI requests with query parameters to be sent on to a further CGI request on another machine), and that many of the parameters had interesting constraints, I realised that while the API might be fine, the implementation we were looking at, Josh Bloch's, encouraged repetition of logic.

Anyway, here's an example to get us started. The problem:

Person person = new Person("John", "Jackson", 1979, 11, 10, "AC2193");
We wanted something more like:
Person person = new Person.Builder()
    .forename("John")
    .surname("Jackson")
    .yearOfBirth(1979)
    .monthOfBirth(11)
    .dateOfBirth(10)
    .nationalInsuranceNumber("AC2193").build();
To keep the code short, we'll use a simpler class as an example, a Person consisting of name and age. As you'll see, even this can be large enough to be interesting.
public class Person
{
    private final String name;
    private final int age;

    private Person(Builder builder)
    {
        this.builder = builder;
    }

    public static class Builder
    {
        private String name;
        private int age;

        public Builder name(String name)
        {
            this.name = name;
            return this;
        }

        public Builder age(int age)
        {
            this.age = age;
            return this;
        }

        public Person build()
        {
            return new Person(this);
        }
    }

    public String getName()
    {
        return name;
    }

    public int getAge()
    {
        return age;
    }
}
Even for 2 parameters, this is quite a lot of code, though thus far there isn't really any logic to be duplciated. Now let's look at a really simple constraint, that values cannot be set twice.

The most obvious way of trying this would be to have a boolean alongside each field in the builder, e.g.:

private String name;
private boolean nameAlreadySet;

private int age;
private boolean ageAlreadySet;
And then in the name(String) and age(int) methods in the Builder you would check the value of that boolean, and throw an IllegalStateException if the boolean had already been set. This is clearly a repetition, which can lead to copy-and-paste errors or just make things hard to change.

In object-orientated programming the usual way of handling this would be to package the field with its boolean in an object and call it, say, MaxOnce. There is a good reason not to go down this path, though, it's difficult to chain MaxOnce with other such types, for example when we want BoundedInt, which prevents values outside a certain range, to work with MaxOnce. So we have a problem that the classes don't work together well. Time for another approach.

It would help if MaxOnce and BoundedInt were more like filters that data gets passed through (or not, if the data is invalid). Enter Parameter.

private final Parameter<String> name = maxOnce("name", null);

private final Parameter<Integer> age = bound(maxOnce("age", 0), 0, Integer.MAX_VALUE);
Notice how bound and maxOnce are chained together in the age parameter It's easy to see how you might write other filters. Here's a largely useless example:
Parameter<Integer> number = not(5, bound(maxOnce(0, "a number from one to ten, but not five"), 1, 10));
For a Parameter that has no default, it might be handy to store the value as an Option, rather than use null, or an empty String or some other sentinel. In another case we want to store the value as a TreeMap (for sparse arrays, mentioned later). So generally we'd like to be able to specify an input type and an output type for a Parameter.
private final Parameter<String, Option<String>> name = maxOnce("name");

private final Parameter<Integer, Option<Integer>> age = bound(maxOnce("age"), 0, Integer.MAX_VALUE);
Note that bound and maxOnce work together for the age parameter, as two filters.

In a few cases, the Parameters that we use are allowed to take multiple indexed values. They are effectively sparse arrays. The Parameter's input type is a Pair<Integer, T> and the output type is a TreeMap<Integer, T> - each incoming Pair gets added to the TreeMap.

private final Parameter<Pair<Integer, String>, TreeMap<Integer, String>> = ...;
We can see that the Parameter is more a declaration than it is an actual value. Then it's quite handy that, actually, Parameter holds no mutable state - we store that in a Map<Parameter, Object> but with slightly better types, wrapped up as a GenericBuilder, and we don't modify that Map, we copy it when we add values, like CopyOnWriteArrayList does in the Java libraries.

Here's the original Person class with a new implementation:

public class Person
{
    private final GenericBuilder finalValues;

    private static final Parameter<String, Option<String>> nameParam = param("name", "The name of the person", Conversion.<String>identity());

    private static final Parameter<Integer, Option<Integer>> ageParam = notNegative(param("age", "The age of the person", Conversion.stringToInt));

    private Person(GenericBuilder finalValues)
    {
        if (realBuider.isDefault(nameParam) || realBuilder.isDefault(ageParam))
            throw new IllegalStateException();

        this.finalValues = finalValues;
    }

    public static final class Builder
    {
        private GenericBuilder realBuilder = new GenericBuilder();

        public Builder name(String name)
        {
            realBuilder = realBuilder.with(nameParam, name);
            return this;
        }

        public Builder age(int age)
        {
            realBuilder = realBuilder.with(ageParam, age);
            return this;
        }

        public Person build()
        {
            return new Person(realBuilder);
        }
    }
      
    public String getName()
    {
        return finalValues.get(nameParam);
    }

    public int getAge()
    {
        return finalValues.get(ageParam);
    }
}
There are a couple of extra bells and whistles in the real code, such as building and parsing URLs containing the parameters. I have another post taking this one step further (using Parameters from code generation) in the pipeline.

Sunday, September 07, 2008

An IRC Bot in Haskell, 20% code, 80% GRR

I decided to look at Haskell more seriously, after mainly using it to learn functional programming and, well, as a posh calculator. So when I came across Don Stewart's little tutorial on writing an IRC bot, I followed it, but with one use case in mind:

In the #scala channel, often it's handy to display a URL to a bug by its index, particularly as the URLs are a little tricky to remember.

Don's code was excellent, very readable, and on my little Asus EEE, all I had to do besides install ghc6 was to install ghc6-network-dev - for some reason the Xandros packages are quite split up.

All worked fine - I tested it in a private channel, then I wanted to make it work on a remote machine, which Eugene Ciurana lets me use. Eugene is mainly a Java programmer, so he doesn't have Haskell installed at all, and as I write this, it's around 9am on a Sunday his time - I'm not going to bother him!

So I wondered about installing ghc as a user, and downloaded the 64-bit binary distribution for ghc-6.8.3. After extracting it I realised I couldn't see a bin/ directory or similar, so I checked the README file, which pointed me at the INSTALL file. So I typed ./configure --prefix=/home/ricky/ghc/, only to find out that gcc was broken on the machine.

Eugene also lets me use another machine, a 32-bit one, but on there I got this error from ./configure:

"checking for path to top of build tree... utils/pwd/pwd: /lib/i686/libc.so.6: version `GLIBC_2.3' not found (required by utils/pwd/pwd)"

dmwit and Heffalump (no, really) from #haskell suggested I try using ghc 6.8.2 instead of 6.8.3, which I am going to try shortly, but I thought of another solution. My little Asus EEE runs ghc (albeit version 6.6) well enough, so I compiled my file. After using gcc on and off for years, I was surprised that ghc 3.hs didn't do anything useful - #haskell suggested ghc --make 3.hs. This produced an executable file called 3, which I promptly ssh'd to both of Eugene's machines. On both it failed because libgmp wasn't present. So I was advised to try ghc --make 3.hs -optl-static - which seemed to almost kill my EEE. But a minute and a half later my EEE returned to its usual speed, last.fm started playing again, and I had a somewhat larger file called 3, which worked on the target machine!

So, if you wander into #scala now and type ~trac 100 it will give you a link to Scala bug report 100.

I spent more than 4 times as long on the config as I did on writing (well, mainly copying, though I copied without a clipboard) the code. Hopefully that will drop next time!

Monday, July 28, 2008

Optional Values in Java

If you take some Java code and write psuedocode representing it, you'll probably find that you don't bother with null checks and you don't bother with getters and setters. Sure, in psuedocode you're lazy, but it's more than that - null is usually wrong, so much so that intentional uses of null look like sloppy code.

In fact, if you're writing an API, you probably want to keep null out of your interactions with your users - you want to make sure they realise their mistake if they give you null and you don't want to give them null, lest they forget to check it. But there are actual times when you need some way of representing an optional value.

One particularly popular approach is to use sentinel values - let's say "" for Strings, Double.NaN for doubles, -1 for ints. Now everywhere you read the value you need to check for the sentinel, or be sure that not checking for it won't cause you problems.

Another approach is to use an empty list to represent no value, and a list of 1 element otherwise. Again you need to check whether the list is empty before getting the result out.

You could make a class that might hold a value, that has methods called hasValue() and getValue(). Again, requires a check.

In all these you need to remember to check before you get the value - not much of an improvement over using null directly.

If I categorise some code including null checks (no, not nunchucks), then we'll have something to toy with:

1. foreach

if (x != null) {
 doStuffWith(x);
}
2. map
String s;
if (x == null) {
 s = null;
}
else {
 s = x.toString();
}
3. fold
int length;
if (s == null) {
 length = 0;
}
else {
 length = s.length();
}
Those were some strange names I gave to these categories! Let's tackle foreach first: Think of a value that might be null as a collection containing 0 or 1 elements - foreach would be a loop that runs 0 or 1 times to do something with the value.

map is a mapping from a domain containing null, to a co-domain containing null, - for example, mapping from rectangular coordinates to polar coordinates should probably yield null for a null input, if it doesn't throw an exception.

fold is a more manageable name for a 'catamorphism', which is a transformation that tends to yield a simpler value than the collection it's applied to (which seems the opposite of a fold in origami). In the case of a possibly-null value, the result is simpler because the result is (usually) a not null value.

Being responsible non-repetitive Java programmers, we'd like to encapsulate our possibly-null value plus the checks into an object with three methods, foreach, map and fold, rather than repeating them everywhere:

interface Optional<T> {
 void foreach(Task<T> task);
  R map(Conversion<T,R> conversion);
  R fold(R theDefault, Conversion<T,R> conversion);
}
(you might really want to make Optional Iterable so that you get Java's foreach loop, rather than providing foreach, as an implementation detail).

In the same way that java.util.Collections.sort can take a Comparator, each of these methods takes in an object that has a method that gets called if and when it needs to be.

interface Task<T> { void execute(T value); }
interface Conversion<T,R> { R convert(T value); }
Let's look at how we can convert the earlier null-using code to code using Optional.

1. foreach

x.foreach(doStuff);
2. map
String s=x.map(toString);
3. fold
int length=x.fold(0,length);
Of course, the likelihood is that you're not lucky enough to already have doStuff stored as a Task, toString stored as a Conversion and length stored as a Conversion, so perhaps you'd use an anonymous class to provide those. Unfortunately the syntax for anonymous classes bloats the code too much to be readable in a blog (or an IDE).

It would be useful to have good syntax for using foreach, map and fold in Java, so that there was at last an attractive alternative to null. For now we'll have to settle for attractive semantics rather than attractive syntax though.

I think this is beautiful because it provides a level of abstraction that gets you further from a potential source of bugs, makes your code more expressive about what it accepts, and lets you do in objects what otherwise would be repetitive.

A complete implementation of Optional is available in Functional Java under the name Option. There, Task is called E, and Conversion is called F. Option is most widely known as Maybe, from Haskell.

May your nulls rest in peace.

Monday, July 21, 2008

Designing an Object

If there may exist an object with a method that is not appropriate at all points in the existence of the object, then the object or the method are flawed.

A class encapsulating a compile phase in an IDE might have a blocking or non-blocking execute() method, plus a getErrorMessages(). There is an obvious protocol in using this class - instantiate, call execute(), call getErrorMessages(). It's not particularly hard to use, though it's also not hard to get wrong. Even if you decide not to help those users who don't bother to learn the protocol, it's worth thinking about whether that protocol should even exist, and what the alternative is.

Many readers would probably, when prompted at least, make execute() return the error messages (or a Future for them), which solves the problem quite well. If you wouldn't, keep adding phases plus methods only appropriate for each phase, to one class that grows and grows, until you end up agreeing or changing career :) Anyway, in this case it's clear that the object was flawed by doing two things one after the other - executing the compile phase and delivering results.

I bet most people could train themselves to spot this flaw and remove it, and if anyone only goes that far as a result of reading this post I'll be happy. But most people are probably quite happy with another flaw, java.util.Iterator.next(), which is only allowed when hasNext() returns true, in most Iterator implementations. But moving next() or hasNext() onto another object doesn't really work for Iterator. For a long time I was unhappy with Iterator, but didn't really have a solution, despite trying a couple of things out.

The biggest use of Iterator directly in Java for many years was in what has since been replaced by a foreach loop. There are some detractors of, well, anything new, but generally the foreach loop was really well received by the Java community. It provides a higher-level interface than the Iterator gives us. We can write a lot of code using the foreach loop that would have been more verbose and awkward to get right using Iterator directly. But foreach is only one abstraction; there are some more that are higher still than it, and don't (but can) depend on Iterator. If you don't know what those abstractions are I really think you should take the time to learn about map, filter and reduce, and the more general but less usable parent of those, fold. But this isn't a post about those, so I'll return to the topic at hand.

Iterator has been shown to be flawed, though flawed in a way that is acceptable to most of us and in a way we're used to, and in a way that seems non-trivial to solve (without knowing about map, filter, reduce and fold!). You might not be in a position to, or even want to, replace Iterator, but at least you should know not to copy its design, or bind yourself unnecessarily to it. You're now either armed with a simple way of deciding between two API designs, or you're about to tell me why I'm wrong.

Happy coding.

Thursday, June 26, 2008

Programming in a natural order

Whenever I'm doing the same thing over and over, a little background thread in my brain starts to wonder if there's a better way. Sometimes I tell it to shut up and let me code, other times I listen. In this case it took me a long time to listen, so it must have been pretty persistent. The first time I noticed it was while writing some lisp. Here goes the usual overly trivial example:

I write (+ 3 4) then realise I want to multiply the result by 5. I have to go back to the start of the expression and change it to (* (+ 3 4) 5). I could easily blame lisp's prefix syntax and maybe define some reader macro so I can write something like (+ 3 4) >> (* 5). But that would solve one case and not really fix the overall problem. Here's the obligatory less trivial example:

I write (+ 3 x) then realise that x needs to be a lambda parameter, so I go back and write (lambda (x) (+ 3 x)). I think it's difficult to make the above >> reader macro work with this.
(+ 3 x) >> (lambda (x)) might work, but it's starting to get hard to read. It doesn't seem as natural as it did for the previous case.

But, as I said, it took me a long time to take notice of this background thread, and in fact when I did I was writing Scala, not lisp. When in lisp I just wrote the code anyway, and it didn't harm me noticably. I never wrote the above reader macro, and as I've never written one, chances are it's unwritable anyway.

The case when writing Scala was where I was looking at an expression, then realised that one of its inputs would be a collection, not a single value. A closer-to-reality example - you have a Client, and a Client has a manager, the contact there that you speak with. So you have:
def sendSpam(client: Client) = emailer.send(marketingTripe, client.manager.emailAddress). Then later you change Client.manager to Client.managers, and change its type from Manager to Iterable[Manager]. Now the emailer protests (at compile time), so you have some options:

1. Change the emailer to make it accept an Iterable[Client]. This is actually quite reasonable, and what I did in the real code this mimics.

2. Change the code to:
client.managers foreach (manager => emailer.send(marketingTripe, manager.emailAddress)).

3. Listen to the background thread in your brain, and blog about an automatic transform from the original version to option 2. Today I'm choosing option 3, as you can tell. To avoid ambiguity, I'll introduce some syntax to put around 'managers':
emailer.send(marketingTripe, ^(managers).emailAddress) will be transformed to the code from option 2 above (though perhaps without a real variable name).

At this point, you might be seriously glad that I am not a committer on the compiler for the language that you use every day. But I think the above might actually be a good idea, and might even be a better syntax for a map with a lambda than what we're used to. The reasoning is: it's preferable to write code in a natural order, rather than the order that the language forces you to.

Wednesday, June 25, 2008

A Cross-Language Generics Trick - Java, Scala and C#

Given a Pair<T, U> type in Java, Scala or C#, such as Map.Entry, Tuple2 or KeyValuePair respectively, you can construct type-checked variadic heterogenous containers that you can write general methods to operate on.

Let's write a Pair interface for Java and C#:

interface Pair<T, U> {
 T _1();
 U _2(); }
For Scala we'll use Tuple2, which has _1 and _2 as well. You could use Map.Entry and KeyValuePair in Java and C# respectively, but they seem to have extra semantic information in their names. I know some readers will be crying out for more semantic information than _1 and _2, but I hope they bear with me a moment.

Eliding the implementation, one could have a line of code like the following easily:

Java: Pair<String, Integer> pair = Pairs.pair("hello", 5);
Scala: val pair=("hello", 5)
C#: val pair = Pairs.Pair("hello", 5);
I expect that's fine with most people. For C# you'd probably change 'pair' to 'Pair' for the method name. Then, to start introducing the trick:
Java: Pair<Double, Pair<String, Integer>> withDouble = Pairs.pair(3.0, pair);
Scala: val withDouble = (3.0, pair)
C#: var withDouble = Pairs.Pair(3.0, pair);
You can see that the type in the Java code starts to look a little messy; this is no accident. Explicit static typing makes us more likely to choose less expressive types. Anyway, we can add a method 'prepend' to the Pair type, which doesn't modify anything, but returns a new Pair consisting of a data item on the left and the original Pair on the right. So we get:
Java: Pair<Double, Pair<String, Integer>> pair = Pairs.pair("hello", 5).prepend(3.0);
Scala: val pair = Pairs.pair("hello", 5) prepend 3.0
C#: var pair = Pairs.Pair("hello", 5).Prepend(3.0);
So prepend must be an interesting method, because it looks like you can use it to add more type parameters to something. Clearly you can't, I'm just chaining Pairs, but it makes a nice effect. So far not very useful; I'll get to that. First let's implement prepend:
Java:
 public class Pair<T, U> { ...
  public <V> Pair<V, Pair<T, U>> prepend(V v) {
   return pair(v, this); } }
Scala:
 implicit def Tuple2WithPrepend[T, U](tuple: (T, U)) = new {
  def prepend[V](v: V) = (v, tuple) }
C#:
 public class Pair<T, U> { ...
  public Pair<V, Pair<T, U>> Prepend<V>(V v) {
   return pair(v, this); } }
The nice part about this way of building up Pairs is that you can write methods to handle them instead of writing one per Pair arity. Specifically, you could gather up parameters for an immutable class then instantiate it in one go. In fact, that's what I do in a prototype for a JDBC wrapper. To wet the tastebuds (sorry, only Java for this one):
List<QuestionInfo> questions=select(conn).asString("question").asString("correct").asString("wrong").as(question).from("questions").toList();
The idea is that the above runs the SQL query: select question, correct, wrong from questions and constructs a QuestionInfo for each result, putting the result into a list.

The surprising thing is probably that there's no reflection or casting going on at all. Each asString (well, after the first one really) builds up more in a chain of generic types, then the .as(question) deconstructs them again. question is actually an F<Pair<String, Pair<String, String>>, QuestionInfo>, which means it's a function that takes 3 Strings and returns a QuestionInfo, roughly.

The above code comes from a working test case I published here.

It turns out that someone else had this idea way way way before I did, and made something professional out of it, though only some of that appears to be statically type-checked.

I hope that what I've showed here proves useful to you, and if you are my team leader and I pointed you at this page, remember that you saw it on the Internet, it's real, so you have to let me write it in our project.

Saturday, April 26, 2008

So You Like For Loops? Zip It Up!

I've written this little for loop many a time, it finds all duplicates in a sorted list of integers:

List<Integer> nums=Arrays.asList(1,2,2,3,4,6,6,7,8,8);

List<Integer> dups=new ArrayList<Integer>();
int prev=nums.get(0);
for (Integer i: nums.subList(1))
{
    if (prev==i)
        dups.add(i);
    prev=i;
}
Now go and read your email or something, and come back to read just the for loop (and the line above it). You have to trace through time in your head to work out what it does. The code doesn't say what it means, but that's ok, right, because it works.. hmm.

Let's make up a type called Pair<X,Y>, and quickly imagine that List now has this nice method, zip. Here's the above list, zipped with a sublist of it starting from 1.

System.out.println(nums.zip(nums.subList(1)));
output: ArrayList((1,2),(2,2),(2,3),(3,4),(4,6),(6,6),(6,7),(7,8),(8,8));
Can you see how that relates to the original list? I hope so. Given this data, how would you find duplicates? Well, you'd look for any Pairs where the X and Y value are the same, easy. We'll call that zipped list 'zipped', of type List<Pair<Integer, Integer>>:
List<Integer> dups=new ArrayList<Integer>();
for (Pair<Integer, Integer> pair: zipped)
    if (pair.x().equals(pair.y()))
        dups.add(pair.x());
This for loop is a common pattern now, it's a 'collector'. At each iteration we have a/the list of dups, and the current pair. If the current pair has equal elements we modify the list of dups to make it have one more. Really, it seems like it should be a general operation, filter:
List<Integer> dups=zipped.filter(new Predicate<Pair<Integer, Integer>>()
{
    public boolean invoke(Pair<Integer, Integer> pair)
    {
        return pair.x().equals(pair.y());
    }
}).map(new Function<Pair<Integer,Integer>,Integer>()
{
    public Integer invoke(Pair<Integer, Integer> pair)
    {
        return pair.x();
    }
});
It's kind of better but the syntax is getting in the way. Hold up your closure glasses to the screen, or if you don't have any, I've kindly repeated the code but using the proposed Java 7 closures syntax:
List<Integer> dups=zipped.filter( { Pair<Integer, Integer> pair => pair.x().equals(pair.y()) } ).map( { Pair<Integer, Integer> pair => pair.x() } );
I hope that helped you read the previous code. Let's go one step further with these glasses, they are now magically type inference glasses. We don't need to specify the type of 'pair' because it's blindingly obvious from the type of zipped. We don't need to specify the type of dups because it's blindingly obvious from the return type of filter:
val dups=zipped.filter( { pair => pair.x().equals(pair.y()) } ).map( { pair => pair.x() } );
It looks to me like the braces in there are a bit redundant, the () after x and y are just annoying, and .equals is a Java design error that our glasses can correct:
val dups=nums.zip(nums.tail).filter(pair => pair.x==pair.y).map(pair => pair.x)
Und viz zis Scala zee transfurmaschun vill be complete! (parody of a parody)

Update: Thanks to David MacIver, who spotted a mistake, I had to add 'map' to each of the non-for-loop examples, and in updating it, I've stopped short of what might be the Scala norm - in a closure such as (x => x+2), where the closure parameter is only used once, you can write (_+2). So above you'd write blahblahblah.map(_.x) instead of blahblahblah.map(pair => pair.x).

Sunday, March 02, 2008

Implementing OOP in Java

Object-Oriented Programming is all about late binding. Java has some support for it via polymorphism, but it is not as late as it could be. Java makes some attempt to guarantee things statically, e.g., method calls are guaranteed to correspond to an actual method at runtime. This has a couple of implications:

1. Some of the dynamism that languages like Smalltalk, Python, Ruby and Groovy have is lost.

2. In attempting to reach that dynamism, programmers end up doing things like: throw new UnsupportedOperationException, because their interfaces are too big, and having smaller interfaces would increase the number, and hence perceived complexity, of APIs (yes, this really is the reason java.util has 'optional methods' in interfaces).

Static typing, particularly when it's done really well, is incredibly useful. So useful that it can replace lots of unit tests, or even make unit testing even easier to write. It's actually possible to guarantee that code cannot have a runtime error, if you write it with that in mind. However, some code really needs to be dynamic, at least temporarily, because it's being written by an amateur, or needs to be swapped in or out at runtime, or is an idea that might not match up with your language's typesystem just yet. In that kind of code, guaranteeing that there are no errors is actually an anti-goal.

So, let's implement this idea of OOP, in Java. Some languages have a symbol type that is quite appropriate for this, but Java doesn't, so we'll use strings. To avoid annoying namespace collisions, we'll call our Object type Dyn, short for Dynamic. I chose this short name to not distract from the meaning of Dyn-using code. A Dyn is an object that has a method, ap, that takes a String and zero or more Dyns as parameters, and returns a Dyn. (Some conversion methods to Java's static types might be useful too)

public abstract class Dyn
{
    public abstract Dyn ap(String name,Dyn... args);
}
And an implementation, just enough to try it out:
public static final Dyn identity=new Dyn()
{
    public Dyn ap(String name,Dyn... args)
    {
        return this;
    }
};
The above Dyn is a bit silly, whatever message you send to it, it returns itself, and that's all. Here's one that holds a Java int and when the message "sqr" is passed to it, returns a Dyn holding the square of that int:
public static final Dyn squarer(final int i)
{
    return new Dyn()
    {
        public Dyn ap(String name,Dyn... args)
        {
            return name.equals("sqr") ? squarer(i*i) : identity;
        }
    };
}
Here I'm using the identity object to represent an error/missing method, which seems broken, but right now we can't actually observe that because there's no way to print a Dyn or convert it back to a Java object, so it doesn't really matter. I could add a toString() to the implementation to be able to see the results. I could write Rails for it, with all the method_missing goodness involved.

My question to you who have read this far is, if Dyn was made more a part of a static language instead of a clumsily-added library as shown here, would you be tempted away from Ruby et al? Let's, for this post, reserve the [] brackets to say 'in here be dynamic code'; any time we don't want the typechecker to look at our code, we put it in there, so we might write something like: Animal animal=new Dog(); [ animal.woof(); ] You could write all your code between [ and ], and gradually move it outside when you know how to make it type check, hence incrementally getting better reliability and performance (but reduced flexibility).

Note that this isn't the same thing as adding explicit static types to a dynamic program. Good static typing doesn't need explicit types everywhere, thanks to type inference.

Would this be an attractive option? Does such a language already exist?

Wednesday, February 20, 2008

When would you choose to repeat types?

I was surprised to see that some developers would prefer to repeat code with different
names rather than using abstractions.

In other words they name types by the way they're used instead of what they are.

I always like to consider the extremes of always applying a rule or never applying it.
If we made every use its own type we'd have lots of conversion functions to write
to avoid code duplication (but of course those functions would be duplicates).

The other extreme would be only naming a type by what it is so you'd never have
NameAndAge and AddressAndYear, you'd only have StringAndInt (or Tuple[String, Int])
and the meaning would only be shown by the use.

Tony Morris generally seems to agree, but he would give names to types when the
typesystem cannot express important things about the type, such as associativity.

AssocF[Int] instead of F[Int, Int, Int]
I've seen people prefer names for types in all cases, so they would never want
tuples or function types in their languages.

I think these programmers have a fear of abstraction. What do you think?

Monday, January 21, 2008

A Trivial Display of How Scala's Type System Beats Java's

This article shows that Scala lets you add methods to objects, depending on their generic types. In Scheme, and other lisps and languages influenced by lisp, there is a construct called a cons, which is a pair of values. Linked lists can be built up by 'consing' pairs together. The first part of a cons can be called the 'car' (if used as a list, this is the head), and the second the 'cdr' (if used as a list, this is the tail). So if you have a cons with a cons as its second element, you can think of that as a compound data structure with three elements. E.g.:

(cons 1 (cons 2 3))

The first value of the second part of that, 2, the head of the tail, the car of the cdr, is known as the cadr. Let's write a Cons class in Java and Scala and then look at how to add the cadr.

Consider this Java code:

class Cons<A,D>
{
    public final A car;
    public final D cdr;

    public Cons(A car,D cdr)
    {
        this.car=car;
        this.cdr=cdr;
    }
}
equivalent to this Scala:
case class Cons[A,D](car: A,cdr: D)
(yes, that's all)

Now let's think about cadr. If a Cons has a car of type A and a cdr of type D, what type is the cadr? It's the type of the car of the cdr, which we haven't got a type parameter for. We could try this:

class Cons<A,D extends Cons<E,F>> but there's a recursion problem here -- F must extend Cons<E,F>>, not going to work. Plus, even if that worked, we could no longer use Cons for simple pairs.

We can make a static method elsewhere:

public static <A,D,E> D cadr(Cons<A,Cons<D,E>> cons)
{
    return cons.cdr.car;
}
That works fine, but it makes cadr somewhat a second-class citizen. It's a shame we can't do pair.cadr. In steps Scala.
implicit def addCadr[A,D,E](cons: Cons[A,Cons[D,E]])=new { def cadr=cons.cdr.car }

Cons(1,Cons(2,3)).cadr gives 2
addCadr, when in scope (it can be imported if it's not written where we need it) defines an implicit conversion from Cons[A,Cons[D,E]] to an anonymous class that implements cadr. So any time we ask for cadr the compiler (not the runtime) looks at our Cons type, doesn't see cadr and looks for any implicit conversions that result in a type that implements cadr. In this case it finds one.

The above is probably not a very practical use, let's think of some. You can make a List[Char] have the same methods as a String, for convenience. You can make a List[Double] have a total method.

(The worst thing about Java generics is how annoying they are to type in blogger!)

Monday, January 07, 2008

In Defence of (0/:l)(_+_) in Scala

A few days ago, Doug posted a rather angry-sounding exit note about Scala, based on two and a half months of 'an in-depth look at the Scala language'. He pointed out some code as an example of how write-only Scala is:

(0/:l)(_+_)

I had no clue what this meant (the first part anyway) at first. Zero Slash Colon One? Is that a new band? I typed it into my Scala interpreter, and while I was typing it, I realised that the One was an Ell. Let's change the name now. l is a bad name. Call it x, xs, or kiwiFruit, but not l:

(0/:list)(_+_)

I then had a bit more of a clue. From the Scala book, I remember reading that operator names that end with a colon are right-associative. In other words, a+b is shorthand for a.+(b), but a+:b is shorthand for b.+:(a). So the above code can be rewritten as:

(list./:(0))(_+_)

This doesn't look a lot clearer, but we can now look up the /: method in the Scaladocs. It's not on List, it's on one of List's traits, Iterable. It's a fold. Here's a longer way of writing the code (and in a way I'd have understood immediately):

list.foldLeft(0)(_+_)

If you're still left bewildered by this version, let's go a bit further.

(_+_) is an anonymous function that takes two values and adds them with the + operator. Let's make up two names and roll them into place. x gets rolled into the first _, y into the second:

list.foldLeft(0)(x, y => x+y)

And if anyone's still not following, what this does is to sum all the elements of list. If the list is List(2,3,4) it looks like 0+2+3+4. Some languages/tools call it reduce (notably MapReduce/Hadoop), some call it inject (Ruby. Any others?). Some languages make you use a for loop, which I assume must be to stop you from getting too cocky about how good your code looks.

So, 1 minute after not understanding the original code, I understood it. The blog in question got mentioned on the Scala mailing list, and Martin Odersky, Scala's inventor, apologised, kind of:

That was my fault. I included it because I liked it, and that for two reasons:

1. (z /: xs) (op) looks like an abbreviation of a left leaning tree
with a `z' on the lower left end (at least to me). I.e. something like

      op
    /    \
   op    x1
  /  \
 z   x0

That's the tree I always draw when I explain fold left.

2. (z /: xs) has the operands in the ``right'' order.
I can see both points, and I'll still use foldLeft. I would not balk at someone else's code using /:. It took me 1 minute to understand, and now I can happily read folds written that way.

In discussions with other Scala programmers, I tried to say that the time taken to learn things isn't as important as how useful they are once learned, but I couldn't find a good way to say it. David MacIver, in an unrelated post to the mailing list, said what I intended to, but much better:

"Optimising your notation to not confuse people in the first 10 minutes of seeing it but to hinder readability ever after is a really bad mistake."

If only I could get him to stop arguing with Ian Clarke and write stuff I want to read!

If I used folds a lot, and perhaps I will someday, I would quite happily use the /: operator. Once I've internalised its meaning I can just get on with reading the names that I chose for things, rather than reading what the language forces me to have. Of course, to most of us, myself included, I'm not that used to folds, but if I considered folding to be just as primitive as +, I'd much rather write /: than foldLeft, just as I'd rather write + than plus.

The rest of Doug's blog really surprised me; I don't know how two people can spend the same amount of time in a programming language's community and get such different results.

My only explanation is that I am comfortable with Haskell, and a long-time Java programmer, so I probably have an advantage when it comes to Scala, which is largely Java minus some bad things, plus some good things from Haskell and many other places.

And while it's in my text buffer:

Don't assume that Scala is only useful for writing web apps, desktop apps, object orientated programming, functional programming, scripting, encoding mathematical properties and concurrency just because that's all that's been discussed on the mailing list this week.

Saturday, December 29, 2007

Make Scala Your Language for 2008

Scala's a statically-typed language based on Java, but with features that make it comparable to Ruby, Groovy, Haskell, Python, Erlang and Smalltalk. It's pronounced "Skah-la", rather than "Skay-la", it has closures, gets rid of Java's controversial checked exceptions, and is almost perfectly interoperable with Java APIs.

There's an official book nearing completion (available now in PDF form), and some very clever people are using Scala (and some not so clever ones, like me). One of the core developers is called Lex Spoon, which has to be a plus for any language. Scala's been cooking, and by the time you finish reading this and procrastinating about whether to use it, it'll be ready.

It is one of those languages where boilerplate isn't welcome, yet is statically typed and supports both OOP and functional programming without blinking. Scala programs can use Java APIs effortlessly, and Scala turns out to be better than Java for testing Java code (despite some integration concerns raised by Ola Bini)!

So how can you use it? Obviously, install it, then you can launch its interpreter (you can use it as a scripting language or a regular compile-to-bytecode JVM language [though the difference is an elaborate illusion]). Here I'll launch the interpreter with the Google Translator API on the classpath:

$ wget -q http://google-api-translate-java.googlecode.com/files/google-api-transla
te-java-0.26.jar
$ scala -classpath google-api-translate-java-0.26.jar
Welcome to Scala version 2.6.0-final.
Type in expressions to have them evaluated.
Type :help for more information.

scala> import com.google.api.translate.{Language,Translate}
import com.google.api.translate.{Language, Translate}

scala> import Translate.translate
import Translate.translate

scala> import Language.{ENGLISH,SPANISH}
import Language.{ENGLISH, SPANISH}

scala> translate("bastante facil",SPANISH,ENGLISH)
res0: java.lang.String = Fairly easy
So it's pretty handy for trying out APIs, even built-in ones. Let's look at replacing all backslashes in a String with forward slashes, presumably to insert the resulting code into our Java program.
scala> "blah\\blah\\".replaceAll("\\","/")
java.util.regex.PatternSyntaxException: Unexpected internal error near index 1
\
 ^
        at java.util.regex.Pattern.error(Pattern.java:1700)
        at java.util.regex.Pattern.compile(Pattern.java:1453)
        at java.util.regex.Pattern.(Pattern.java:1130)
        at java.util.regex.Pattern.compile(Pattern.java:822)
        at java.lang.String.replaceAll(String.java:2190)
        at .(:4)
        at...
scala> "blah\\blah\\".replaceAll("\\\\","/")
res2: java.lang.String = blah/blah/
As you can see it's useful for prototyping little bits of Java too. But Scala in this case has a better way, too. Strings delimited with """ do not need any escaping (and can be multiline):
scala> """blah\blah\""".replaceAll("""\\""","/")
res4: java.lang.String = blah/blah/
Now the only escaping necessary is what Java's regex implementation requires.

Scala's method call syntax can be used without punctuation in some cases. x.y(z) can be written x y z, and x.y() can be written x.y. It also has implicit conversions, so if you define a conversion from type X to type Y, it looks as though X has all Y's methods. The type Int has a conversion to RichInt, and RichInt has a to(Int) method, so I can do:

scala> 1.to(10)
res0: Range = Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
or even better:
scala> 1 to 10
res1: Range = Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
The lack of punctuation makes some things really attractive:
scala> (1 to 10) ++ (20 to 30) map (_.doubleValue) map Math.sqrt filter (x => x-
x.intValue>0.5) map (x => x*x) map Math.round
res60: Seq[Long] = Array(3, 7, 8, 21, 22, 23, 24)
This code takes the range 1 to 10, the range 20 to 30, and concatenates them together, then gives another range with the same values as the first but as doubles, then another with the same values as the second, but square rooted, then it gives another range with only those square roots whose fractional parts are greater than 0.5, then another range with the remaining values squared, then another with rounded values of those.

You can read the code pretty much like a bash pipeline. Here's the same thing how I imagine a bash programmer would like it:

concat $(range 1 10) $(range 20 30) | map doubleValue | map Math.sqrt | filter x-x.intValue>0.5 | map x*x | map Math.round
As with bash, each new Range does not stomp over the memory of the previous one.

Let's insert the punctuation again to see how it looks with Java-style punctuation:

scala> 1.to(10).++(20.to(30)).map((_.doubleValue)).map(Math.sqrt).filter((x =>
 x-x.intValue>0.5)).map((x => x*x)).map(Math.round)
Eek! I think it's safe to say we wouldn't write such elegant code so often if we had to write (and read) the punctuation!

This use of methods as if they were infix operators is really powerful; so powerful that it is used for what we normally call infix operators. 3+4 is just 3.+(4) (operator precedence rules are preserved though).

That's enough for now.

Sunday, December 16, 2007

A Functional Way of Testing OOP Programs

A message in OOP implies effects on entities[1], rather than mathematical functions. If you use mathematical functions in your code, how often they're evaluated isn't important:

    print cos 0*cos 0 is equivalent to:
    let x=cos 0 in print x*x
If you instead say that cos 0 is a message you send to an object, then you can't make that optimisation without knowing how the code you're calling works, because you'd be eliminating a message. cos 0 as a message may cause effects that you can't easily see as a caller; collapsing two messages to one can introduce different behaviour.

However, most of the time that you send an object a message it doesn't appear to perform an action, it just returns you some value. I'll name a method called for its value a function, and a method called for its effects simply a method.

If you can intercept effects that methods cause, then the method no longer causes effects, but describes them. In other words, if you notice an action and control whether it really happens, you've made the method appear to be a function, and you've made it easier to test, because you can observe all the actions that happen.

Such an interceptor, a body of code that intercepts effects as described could use metaprogramming of some sort, perhaps by changing classes directly at runtime, perhaps through compile-time techniques such as macros. However implemented, it would apply an automated transformation to the innards of methods. Let's see what we'd want that to generate, by writing the result of the transformation ourselves.

The interceptors in the following code vet, log or reject effects. I've made an interceptor return an interceptor on each call so that interceptors themselves can be implemented using return values rather than state changes. The code in this article is something a bit like Java, so that implementation details of a particular language don't get in the way.

public Interceptor writeSomeTextToFile(interceptor,text,file)
{
    (interceptor,val out)=interceptor.new FileStream(file)
    interceptor=interceptor.write(out,text)
    return interceptor.close(out)
}
It looks doable, but pretty ugly. One part of it can be improved. If we change Interceptor so that it can has a type parameter, we can get rid of the tuple return that interceptor.create gave:
public Interceptor[Nothing] writeSomeTextToFile
    (Interceptor[Nothing] interceptor,text,file)
{
    Interceptor[FileStream] out=interceptor.new FileStream(file)
    Interceptor[Nothing] two=out.write(text)
    return two.close(out)
}
It's really up to the Interceptor now what it does with that code. It could run the effects there and then, store them and never execute them, and our code would be none the wiser, because we haven't seen any mechanism for getting values out of the Interceptor.

The code processor to add interceptors would be pretty handy. Let's say we have an annotation that instructs some build tool or macro to do that, so now our source code looks like:

@WithInterceptor
public void writeSomeTextToFile(text,file)
{
    val out=new FileStream(file)
    out.write(text)
    out.close()
}
Our unit test can look like:
val passed={
    val ceptor=new LoggingInterceptor()

    return ceptor.invoke(writeSomeTextToFile,"hello","/etc/passwd")
                 .matches(list(creating(FileStream,"/etc/passwd"),
                               writing(FileStream,"hello"),
                               closing(FileStream)))
}
It's now clearly far easier to reason about and test the method, because you can trivially observe all of its side-effects. You could even decide which ones to allow, externally to the code, to implement a sandbox. In the usual case that you want to execute the effects immediately, you can still do that.

This is a very long-winded way of showing that methods are functions in disguise. Allowing methods to have difficult-to-notice side-effects makes them harder to reason about. It's harder to write tests for them, it's harder to think about them.

This interceptor technique could be applied to existing code, to compare the effects that a 1,000 line method has, to the effects that a refactored version of it has, in the same way we often write unit tests that compare returned values. It seems to make such a good regression test framework that I'd be very surprised if it didn't already exist for most mainstream languages.

The interceptor technique is very heavily based on monads (and may even just be a monad). Haskell programmers, the biggest monad users today, even have special syntax for the interceptor chaining; the translation I mentioned is built into their compiler. In fact, they can do all the things OO programmers do, but they make it harder to have unwanted side effects. To my knowledge though, Haskell's IO monad is largely implemented as a compiler hack, so it's hard to write the same tests for side effects that I've showed in this article.

[1] "in object-oriented programming languages such as Smalltalk or Java, a message is sent to an object, specifying a request for action." -- http://en.wikipedia.org/wiki/Message

Thursday, November 01, 2007

Java 7 Example - Writing Your Own Foreach

One of the promises of closures was that if Java 5 had closures instead of foreach, you could have implemented foreach as a method. Let's put that to the test with the Java 7 prototype.

Firstly, the 'control invocation syntax', which is a little subjective, hasn't been implemented in the prototype, so anything I show here is certainly less than foreach could be with closures.

Here's a simple attempt:

public static <T> void foreach(T[] ts,{T=>void} block)
{
    for (int a=0;a<ts.length;a++)
        block.invoke(ts[a]);
}
I can call this like so:

foreach(new String[]{"hello","world"},{String s=>System.out.println(s);});

I found that I kept repeating one error in testing out this prototype, namely forgetting the ; for a statement in a {something=>void} closure.

Anyway, the above doesn't work with continue, break or return. Those are not bound yet by the closures prototype. No matter, let's roll our own (ignoring return; I don't know of a way to apply the following technique to return).

Not only can we pass a closure to a method, but the method can pass a closure to our closure! No, I've not yet gone mad:

public static <T> void foreach(T[] ts,{T,{=>void},{=>void}=>void} block)

Perhaps the T,{=>void},{=>void} is better abstracted into a ForeachControl class or something. Imagining that it was, the T field would be called 't', the first {=>void} would be called 'brake' (as in break, but avoiding collisions with the keyword), and the second {=>void} would be called 'cont' (as in continue).

For now, I'm quite happy to use the above. I'll just reiterate it:

{T,{=>void},{=>void}=>void} is a function type that takes a T, and two {=>void}s and has no return value. A {=>void} is a function type that takes nothing and returns nothing, analogous to Runnable. Here's some example usage:


String[] input={"fish","print","fingers","don't print"};

foreach(input,{String s,{=>void} cont,{=>void} brake=>
        if (s.startsWith("fish"))
                cont.invoke();

        System.out.println(s);

        if (s.startsWith("fingers"))
                brake.invoke();
});
Ok, that kind of looks like a foreach statement now, plus some baggage for loop control. Actually that's as far as I can go in the current prototype. Let's implement foreach then.

cont and brake both need to 'send a message' to the foreach method, without allowing the closure to finish. Without convoluting the usage code above, I can do that by making cont and brake throw exceptions, which is very similar to how continue and break are planned to be supported in closures, except I'm doing it in-language.

public static <T> void foreach(T[] ts,{T,{=>void},{=>void}=>void} block)
{
    class Continue extends RuntimeException { }
    class Break extends RuntimeException { }

    for (int a=0;a<ts.length;a++)
    {
        try
        {
            block.invoke(ts[a],{=>throw new Continue();},{=>throw new Break();});
        }
        catch (Continue c)
        {
            continue;
        }
        catch (Break b)
        {
            break;
        }
    }
}
Look at the block.invoke line. I'm passing two closures to block.invoke - one that throws a Continue and one that throws a Break. Other than that, this method is pretty simple.

As I've said elsewhere, even when/if the control invocation syntax appears, you won't be able to implement foreach exactly as in Java 5, because int cannot be a type parameter, and the closures spec doesn't specify any boxing between int and Integer for type parameters.

Even if you never use this code (I won't!), you can see at a small scale the power of thinking in closures, especially for implementing language features. This is one of the reasons why Smalltalk was such a small language - you could implement much of what Java programmers think of as language as library methods. Lisp and FORTH are small languages (at least conceptually - ignore Common Lisp!) for similar reasons. Java 7 is aiming in the same direction.

Wednesday, October 31, 2007

Java 7 Example - Pattern Matching

One way you can measure a programming language is by taking a feature, either one that it has, or not, and seeing how close you can get to implementing that feature without writing your own parser, etc. Let's take a look at (and copy!) one of Scala's (and many other languages') features; pattern matching:

animal match {
    case Dog() => "woof"
    case Cat() => "meow"
}
It's very similar to a switch statement, and the above really doesn't show how flexible pattern matching is, but it will suffice for now. The usual way of writing the above code in Java would be with some nested instanceof checks and casts, or by adding a speak() method to the Animal type hierarchy.

It's not always practical to add methods to types directly in Java.. e.g., if you're dealing with classes you don't control. And instanceof is fallible - you don't want to have: if (animal instanceof Car) pass compile-time checks, but it does. So let's see how close we can get to the above pattern matching using the Java 7 prototype. I hope you can do better than me!

Here's what I'd ideally want in Java:

Animal animal=Math.random()<0.33 ? new Cat() : Math.random()<0.5 ? new Dog() : new Horse();

System.out.println(match(animal,
                        {Cat c=>"meow"},
                        {Dog d=>d.name+" says woof"},
                        {Horse h=>"neigh"}));
What type would match take as parameters? For now, let's imagine that we're always dealing with Animals, and always returning Strings.

public String match(Animal animal,{? extends Animal=>String}... cases)

That's not legal - {? is an "illegal start of type" according to the compiler. Neal said that because the things on the left hand side of a closure automatically have ? super in their types, I can't also have ? extends. If I replace it with the interface that javac generates it compiles fine:

public String match(Animal animal,OO<? extends Animal,String,null>... cases)

(the null part there specifies the exception types that may be thrown - in a function type you can omit that)

We can't actually call that method without getting at least a warning from the compiler, thanks to varargs using arrays instead of generics. I'm sure that must have made sense to someone at the time. If I convert it to List<OO<? extends Animal,String,null>> cases, I still have a problem. Inside match, I don't know what type ? is, so I can't do anything with it. Next trick then:

class Case<T>
{
    public final Class<T> clazz;
    public final {T=>String} function;

    public Case(Class<T> clazz,{T=>String} function)
    {
        this.clazz=clazz;
        this.function=function;
    }
}
Now I could have List<Case<? extends Animal>> as the parameter type. Here's some sample usage then:
System.out.println(match(animal,
                         new ArrayList<Case<? extends Animal>>(){{
                             add(new Case<Cat>(Cat.class,{Cat c=>"meow"}));
                             add(new Case<Dog>(Dog.class,{Dog d=>"woof"}));
                             add(new Case<Horse>(Horse.class,{h=>"neigh"}));
                         }}));
Note that I'm taking advantage of a little trick for creating lists inline by creating an anonymous subclass of ArrayList and providing a static initialiser. Verbose? Yes. Ugly? Yes. But enough about me. That code will be gone in a moment.

Look at each line. I've got Cat three times in the same line. Ugh. In fact if I make match generic, so that it can return something other than String, then I'll have to add a type parameter to Case for that, and then those lines become even worse. There must be a better way.

I can use a fluent interface/embedded DSL, or, erm, in real words, "readable code" by making match(animal) return a matcher, and putting a method on it, add, that has a type parameter, U, and takes a Class<U> and a U=>String. In fact, let's go the whole generic hog and make it take a Class<U> and a U=>R, where R is the return type we want. When we've finished adding cases, we call done(), which returns R.

Usage:

System.out.println(match(animal)
        .add(Cat.class,{Cat c=>"meow"})
        .add(Dog.class,{Dog d=>"woof"})
        .add(Horse.class,{Horse h=>"neigh"})
        .done());
One step at a time then. match is a simple wrapper method around a type called Matcher, that lets us avoid writing new Matcher<Animal,String>:
public static <T,R> Matcher<T,R> match(T t)
{
    return new Matcher<T,R>(t);
}
Matcher is a class that stores the T passed into its constructor, and an R to return, which is initially null. It has a method, add, that has a type parameter, U, which extends T. Having U extends T guarantees I don't add an invalid case, such as one that tests whether an animal is a Car.

class Matcher<T,R>
{
    public final T t;
    public R r;

    public Matcher(T t)
    {
        this.t=t;
    }

    public <U extends T> Matcher<T,R> add(Class<U> aCase,{U=>R} f)
    {
        if (aCase.isInstance(t))
            r=f.invoke(aCase.cast(t));

        return this;
    }

    public R done()
    {
        return r;
    }
}
The type parameter U is declared to extend T so that you cannot add a case that is impossible, e.g., .add(Car.class,{Car c=>"beep"}) (which makes no sense unless a Car is an Animal).

Get this code, as one compilable/runnable file.

Tuesday, October 30, 2007

Java 7 Prototype - Surprises and Expectations

In my first week of testing the prototype, I found quite a lot of bugs, and some more subjective defects.

Neal Gafter seems amazingly fast at fixing bugs, so there's probably not much point reporting any bugs on this blog. I'll run through some surprises instead. If you want to see the bugs I found, take a look in the test/ directory in the prototype. Neal put some of my bug reports in as Clarkson2.java etc. It looks like he uses some automated testing on those, so if he breaks one he should know before I report it again!

If there's anything in this code that you don't understand, just ask. I mainly wrote it to test the prototype, so I wasn't overly concerned with writing good code. Most of these code samples are from bigger programs that I chopped down whenever I found a bug.

And now to the meat.

1. Definite assignment rules make it difficult to write recursive closures.

(1)
{int=>int} factorial={int x=>x<2 ? x : x*factorial.invoke(x-1)};

The above only works if factorial is a field, not a local variable, because factorial is not 'definitely assigned' on the right hand side of the =. I've been playing with Scala a bit recently (which has given me some good fuel for testing this prototype with), and it doesn't have this restriction. After a conversation with David MacIver, a Scala programmer rather than a dabbler like myself, we came to the conclusion that it's possible to cause a NullPointerException in similar code to the above in Scala.

Lo and behold, Neal replied with much the same argument - if the definite assignment rules were relaxed, the following code could fail, or even do undefined things:

(2) {int=>int} factorial=f({int x=>x<2 ? x : x*factorial.invoke(x-1)});

If f() invoked the closure, then factorial would be accessed before it had been assigned a value. In Scala that is guaranteed to give a NullPointerException, because all variables are assigned to null/0/false before being assigned their real value. In Java, the verifier would not load the code, because it would possibly use values that had been in memory before.

However, for the actual case above (not (2), (1)), it's easy to see that the closure is not invoked before factorial has been assigned a value. I think this idiom is useful enough to make a special case for, but then I'm not involved in writing either the code or the specification so I can't really estimate that task.

The obvious workaround would be:

{int=>int} factorial=null;
factorial={int x=>x<2 ? x : x*factorial.invoke(x-1)};

..except that local variable capture is not supported yet. The current workaround is to make factorial a field instead of a local variable.

If I ever get my head around combinators properly I think I'll have a better workaround.

2. Java 5's foreach statement cannot take a closure.

This code fails:

for (final String s2: {=>asList(args).iterator()});

This code works:

Iterable it={=>asList(args).iterator()};
for (final String s2: it);

The only difference is that I explicitly made closure conversion happen. Typecasting would not fix it (ClassCastException). This is apparently as specified, as a foreach is only specified to take an Iterable or an array. It's not a huge issue, and I can't think of any use cases, but it's still a surprise.

3. Autoboxing doesn't apply to function types.

{Integer=>Integer} f={int x=>x*2}; is a compile error.
{int=>int} g={Integer x=>x*2}; is a compile error. This doesn't look insane on its own, but because generic type parameters cannot be primitive types, it has repercussions. I can't write a generic map function and use it like this:

Iterable<Integer> mapped=map(asList(1,5,11,26),{int x=>x*x});

I have to use the more verbose and more indirect-looking {Integer x=>x*x}.

There's no way of writing a single generic method that converts a primitive function to a wrapper function, again because generic type parameters cannot be primitive types. I could write 8 individual methods, e.g.:

public static {Integer=>Integer} lift({int=>int} f)
{
 return {Integer i=>f.invoke(i)};
}
etc.

However, there's again no way of generalising those to make them work with {int,int=>int}, etc. There is no subtyping relationship between different function types, except the covariance and contravariance rules, quickly demonstrated here:

{Number=>Number} f={Object o=>5};

The above compiles because any Number input is obviously also an Object, and because the output, 5, is obviously a Number (autoboxing taken for granted).

The lack of autoboxing also means that sometimes you'll have to explicitly supply the generic types. Here's an example:

class Main
{
        public static void main(String[] args)
        {
                int i=id().invoke(5);
        }

        public static <T> {T=>T} id()
        {
                return {T t=>t};
        }
}
This code won't compile, because the compiler judges the <T> in the call to id() from main to be int, which cannot be a type parameter. Neal says this isn't a bug. This version compiles:
class Main
{
        public static void main(String[] args)
        {
                int i=Main.<Integer>id().invoke(5);
        }

        public static <T> {T=>T} id()
        {
                return {T t=>t};
        }
}
I think this is a bug; it seems that inference should pick Integer instead of int in the first case.

Another implication of the lack of autoboxing is that when the closure invocation syntax arrives, that Neal promised would let you reimplement the foreach loop yourself as a method, you won't be able to. I expect this will work, if you write your own foreach method:

foreach(Integer i: asList(3,4,5))
 System.out.println(i*i);
but this won't:
foreach(int i: asList(3,4,5))
 System.out.println(i*i);
4. Closures cannot implement generic methods.

This one is much easier to describe in code than words. Given:

interface Identity
{
 <T> T id(T t);
}
..it is impossible to implement this with a closure. I think Haskell allows something like this. Scala doesn't. A use for this would be in implementing some kind of Either type, where an Either<X,Y> may hold an X or a Y, and you don't want to actually have to test which it is, just call a method in Either, supplying a function to run if it holds an X, and a function to run if it holds a Y. The return type of that method should be generic.

Stay tuned for some examples that actually do work with the prototype, at least one of which is actually interesting!

Monday, October 22, 2007

Life in the old Java yet - Closures Prototype

I get home from eating some overpriced underportioned seafood, and drinking a few stouts, phone my girlfriend and check my email. Nothing out of the ordinary, nothing interesting.. but wait! An email from Neal Gafter with a closures prototype! Wow!

So I download it, follow the instructions and it fails. Hmm. I'll try on Linux. javac -version works. I write my first working Java program with closures. I write my second! I mention it in an IRC channel or two, excitedly! I remember that I'm still on the phone and have no idea what she said for the past 5 minutes, so I lower my laptop lid. I get off the phone as quickly as possible, which is to say we talk for another half hour, which is to say she talks for another half hour.

An hour or two after that I send Neal a list of about 5 or 6 problems with the prototype, but go to bed happy, especially having drunk a Spitfire. A beer, not a WWII aeroplane.

First thing in the morning, he's fixed the problems, so I download again. The same problems are there. Hmm. Oh, right, the filename included the date. What's today's date (it was 2am today that I sent the emails)? 2007-10-22. But Neal's in America, and they're backward, so 2007-10-21. Ok, got the right file now. Still fails in Windows, and at least one of my reported failures still fails but for a different reason. I start playing again, and some more code fails for the same reason as the first, so I give up for now.

There's much more fun in breaking a prototype compiler than a production one!

Ok, new day, and I'm at my girlfriend's house for the evening. Neal's just sent another prototype, and it still doesn't work in Cygwin. I can't get my laptop online to connect to Eugene Ciurana's Linux box that I was testing on, so I start looking at the bin/javac script. I see and fix the not-on-Windows problem. It's passing a full path to lib/javac.jar to javac, and that includes /cygdrive/c, Cygwin paths, which Java doesn't know about. I find a fresh batch of bugs and surprises. After finding the same bug twice from unrelated pieces of code (and getting pestered to watch a film) I stop trying. Neal confirms the bugs, but nothing new arrives the next day.

Over the next few days I find more and more bugs, and Neal fixes them all. There are a few bugs that turn out to be features; they're actually in the spec that way.

Now that I have a fresh set of bugs waiting to be emailed to Neal, he's just published the closures prototype. You can find it over at his blog.

I'll shortly publish some surprises from playing with the prototype, then some examples of what you can (and can't) do with it. In a less commentative style..

Blog Archive

About Me

A salsa dancing, DJing programmer from Manchester, England.