May 16th, 2008

Why bloggers stop - overjustification is the prelude to the decline0

Here’s an interesting essay that deals with motivation. Specifically, two observations about motivation:

  1. Explicit motivation easily replaces and pushes out implicit motivation (implicit motivation is doing it ‘for yourself’)
  2. Explicit motivation is easy to lose - and implicit motivation does not return

    For more details including a description of an experiment that tests this theory, read the article.

    So, here’s a thought: Perhaps this applies to blogs?

    A lot of people, apparently, start a blog mostly for themselves or for a close-knit band of friends. So did I. However, at some point, you get your hopes up, or you make something for general consumption.

    For example, I had high hopes for the bush countdown widget which Alper and I posted to digg and reddit (bombed, though since then on digg a site with a very ugly widget did make it. I’m not bitter :-P ). A post with critique on a temporary measure by reddit, a news aggegation site, did not bomb and generated a lot of traffic.

    Almost immediatly since then, I sort of lost interesting in blogging, and eventhough I did have plenty of time, this is the first new article in over a month. Trying to analysing my own reasons for starting to blog, and then losing interesting like this, I do get the feeling it’s a simple question of being no longer satisfied to do it ‘for myself’, since the more or less ‘external motivation’ of having a popular blog.

    Interesting? Maybe it applies to you? Eh. I think so.

Alternatives to Closures (java)6

Gafter and Gosling themselves have written a proposal to add closures to java7.

If it happends, I’m switching to something else. That proposal makes Java a lot like Python. Except, of course, Python is a lot better at being pythonesque than java ever will be. duh.

Here’s an example straight from the closure proposal:
int(int) plus2 = (int x) {return x+2;};

In order to make this discussion a bit more lively, I’ll be focussing a lot on an actual live example from the JDK where Ruby and Python use closures - sorting a list. In python, sorting a list of integers in order of absolute value would work like this:
a = [-2, 1, -10, 3]
def compareFunction(x, y):
    return abs(x)-abs(y)
a.sort(compareFunction)

In the current version of java, the same functionality would be implemented as follows:
List a = Arrays.asList(new Integer[] {-2, 1, -10, 3});
Collections.sort(a, new Comparator() {
    public int compare(Integer x, Integer y) {
        return Math.abs(x)-Math.abs(y);
    });

If the closure proposal is adopted, this code fragment would probably look like this:
List a = Arrays.asList(new Integer[] {-2, 1, -10, 3});
Collections.sort(a, (Integer x, Integer y) {return Math.abs(a)-Math.abs(b);});

First, an analysis of the (dis)advantages of each of these 3 fragments:
Python v. current java
The python code is shorter. Walking proof that creating initialized lists should be simpler, but that’s not related to closures. The relevant bit, the closure, uses a combination of a named function (which does unfortunately contribute a variable name, which is annoying when it isn’t needed. You could use a lambda here but that only works for very simple one-liners, not always an option) and the general property in python that functions can themselves be used as objects. It’s a lot shorter vs. the java example.

What’s missing is typing information. There is no python definition file ANYWHERE that explicitly explains that the parameter to a list’s sort function must be a function with 2 parameters that returns an integer. There’s not even any explicit mention that the parameter must be a function at all. a.sort(”hello, world!”) does ‘compile’ - it generates a run time error. This is normal pythonic behaviour, and it’s very un-javalike. Java sacrifices short code for large scale maintainability: While in a small project you’ll just remember how everything works, in java the combination of explicit typing everywhere and the existence of tools like javadoc allow Eclipse to auto-complete your attempt to call the sort method, offer you to generate the exact comparator boilerplate (so that you know parameters and return type that you’re supposed to supply) and can show a popup of javadocs.

That discussion applies generally to the differences between java and python/ruby/javascript. It’s relevant here because the closure proposal works well… in P/R/JS, NOT in java.

Java vs. Proposal
The proposal code is as short as the python code except basic types are added. However, some type information has been lost between old and new: In the current java example, the parameter is a java.util.Comparator. If I’m confused about particulars, I can look there for relevant javadocs, and if I write a method that returns a Comparator, I don’t need to put anything of substance in the javadoc for this method assuming the methodname itself makes sense (ie: getAbsoluteIntegerComparator() or some such). In the new example, the ‘return type’ of that method would become an int(Integer, Integer) which might as well be something for adding two arguments together. Or for calculating the difference. There are literally infinitely many operations that map 2 integers onto 1 integer. (Preferably, actually, an enum with 3 choices, but, eh, that’s for another time). There’s no one specific type and there’s no javadocs to refer to.

That almost seems analogous to the choice of Exception to throw: A lot of programmers new to java, myself included for over a year, just picked a nice Exception from the java runtime library that sort of fit the problem. Now, though, I always make my own exceptions. It’s a bit more work (IDE helps) but it’s helped me avoid tons of bugs, and it makes code way more readable. It also allows me to pile generic conditions of a certain exception into the javadoc of the exception itself, instead of repeating myself over and over, re-mentioning it in every relevant method that throws it.

In other words, recycling exceptions is a bad idea. If you agree with that, I’m tempted to say that logically you should also strongly dislike this closure idea.

Alternatives

So, while the closure java is pretty bad, it still has one big thing going: It’s much smaller and more convenient. On the user side it’s less code, and on the library author’s side, it’s way less code, you don’t even need the separate interface.

Let’s see how close we can get with java5-inspired syntaxis tricks. Through a number of proposed, low-impact changes, I’m going to make it possible for the library user to sort this list as follows:
List a = new ArrayList(-2, 1, -10, 3);
a.sort(new Comparator(Integer x, Integer y) {return Math.abs(x) - Math.abs(y);});

Analysing the code above, this looks quite decent. It’s very short yet it loses none of the expressiveness and typing of the current original. It can also be reduced to plain old java1.4 code if you must, unlike the closures. There are 3 different improvements here.

1: interface model methods

Currently, ‘a.sort()’, where a is a List, doesn’t compile. It’s an error; the List interface has no sort method. Even if a would be an ‘ArrayList’ type, there’s no sort. Sort currently resides in ‘Collections’, but starting from java 1.6, interfaces are allowed to have static methods. It would make sense for the sort() method to live in the List interface, as only lists can be sorted.

That would lead to List.sort(a) which is still ugly. The next step is a compiler-optimization step only; it compiles down to the exact same code as the old way, it’s just easier to write, and easier to read. If a method cannot be found in the structure itself (not in the class, or the superclass, or its superclass, etcetera), then look for all relevant interfaces with the same signature except with an extra parameter as first parameter: the object type itself.

In other words, a.sort(Comparator) compiles to List.sort(a, comparator), provided the following caveats are true: ‘a’ is of a type that has no (non-static) ’sort’ method anywhere in its hierarchy. There is exactly one static ’sort’ in the hierarchy of a’s type, which has as first parameter something compatible with ‘a’ itself. This avoids problems with multiple inheritance (if two different interfaces both have candidate methods, then the compiler refuses to compile, and you have to fix the code by hand. It won’t happen often, but where it does happen, compiler error is much preferred over vague and hard to remember rules of precedence. That’s asking for bugs).

2: function interfaces

Any interface that has the @Function annotation (and has only 1 method not copied over from Object.java) can be implemented using the special function syntax:

new interfacename(parameters for method){method body};

Any generic types can be specified as usual (between interface name and the parameters, in lesser than/greater than brackets), but they will be inferred where this is possible (usually possible if the parameters themselves cover all generic types. Usually true, and true in this example). The parameter list and method body simply become the implementation of the sole method inside the interface. This eliminates the useless repetition in most function interfaces: The ‘Comparator’ has a single method named ‘compare’. Gee whiz. The method could be called ‘flooburgle’ at this point; the name of the interface itself covers the meaning perfectly already.

3: Collection literals

Creating ready initialized versions for the collection interface (a map, list, or set initialized with values in the code itself) is a real pain. Try to properly make a constant map. It’s ridiculous. Here’s the answer:
private static final Map HTML_CODES;
static {
  Map t = new HashMap();
  t.put(404, “Not Found”);
  t.put(403, “Forbidden”);
  t.put(100, “Continue”);
  HTML_CODES = Collections.unmodifiableMap(t);
}

Fixing THAT, either with actual literals or with library cruches like an Object… constructor for e.g. ArrayList - that’s useful. Cuts down on massive boilerplate - boilerplate you absolutely need to do it ‘right’, like the above example.

This closure thing takes attention away from more important fixes, and takes java entirely in the wrong direction: The direction of becoming a poor man’s python. Being the dynamic programming language’s retarded cousin is, hopefully, not where java is going to go. It needs to take its current stance as king of the static languages and expand on this - show that it beats pure dynamic programming whenever the projects grow beyond the ability of one man to completely comprehend.

Imhotep theme designed by Chris Lin. Proudly powered by Wordpress.
XHTML | CSS | RSS | Comments RSS