Wednesday, March 30, 2005

Windows INI files in Java

For reasons of cross-language compatibility, I have a set of user preferences stored in Windows INI formats. I'd like my Java applications to see these, so a quick Google search turned up an excellent solution. [ini4j] is a Java preferences API implementation using Windows INI files for backing store. Also, there is a simple, obvious API for direct handling of Ini two-level maps. And the whole jar comes in at a svelte 25k. Well done!

Chance meeting

While perusing Ruby Buzz I notice a post from Premshree Pillai about Yahoo's new Yahoo! 360°. It's a blog, a scrapbook, an address book and friend/connections web application aimed at those who's social life is online.

Oddly enough, I started chatting with Prem and found out he works for Yahoo! in Bangalore. I mentioned Yogi Kulkarni who was a top dog developer in our Bangalore office when I was at Dell in Austin (we had a 24-hour development cycle). Wouldn't you know — he knew Yogi! They met a PythonRuby meetup. Even on the other side of the globe six degrees of separation applies.

UPDATE: Oops, it was a Ruby meet, not a Python one.

Friday, March 25, 2005

Firefox and the acronym tag

I just stumbled on something cool with Firefox. Try using the acronym tag, thus:

<acronym title="Spell Out The Acronym Here">SOTAH</acronym>

And the associated stylesheet:

acronym {
  border-bottom: 1px dotted #222;
  cursor: help;
}

The result is YATLA. I especially like the mouse pointer change (at least on Windows).

Thanks to this page on ISBN bookmarklets.

McCallister on Rails

Clever Brian McCallister (all people named Brian are clever -- trust me) has a nice insight regarding Rails v Java: in the terminology of The Innovators Dilemma, Rails is a disruptive technology against the sustaining technology of Java. Honestly, I've never seen anything quite like Rails for setting up straight-forward web applications.

Sunday, March 20, 2005

And now for something different

I type too many serious posts. Where's the fun in that? Well, here's a bit of amusement -- Toogle: Toogle. Go try a search, although I am a little disappointed at binkley.

Thanks to why, the lucky stiff for mentioning this.

Wednesday, March 16, 2005

Ruby Quiz

A very nice site, Ruby Quiz, has a list of programming quizzes along with solutions and commentary. It is focused on Ruby, but the quizzes are written generically and pose nice problems in any modern programming language. Java and its ilk are bondage and discipline languages; Ruby and friends are dynamic languages. But the are both usable for these quizzes.

Monday, March 14, 2005

The excellent bsdiff utility

Colin Percival wrote the very excellent bsdiff utility which makes very size-efficient binary diffs. Starting from there, it is not too difficult to write a script for making binary diffs of directory trees, files and directories added, removed or changed. It is the binary counterpart to diff -Naur. I named it dar after tar. In a test run, I made a binary diff between 1.5.0 1.5.0_01 of the JREs included in the JDK. The dar file is 1.5Mb. A bzip2ed tar file of the whole JRE at maximum compression is 25Mb. Feeback welcome.

Wednesday, March 09, 2005

One of these things is not like the others

Are these not equivalent?

copy(new FileInputStream(new File(".")), System.out);
copy(new File(".").toURL().openStream(), System.out);

Oddly, they are not.

The first line throws a FileNotFoundException (misleading as the error message states . (Access is denied)), whereas the second copies a sorted file listing, one file name per line. I learn something new every day.

Tuesday, March 08, 2005

Editor for Ruby?

I'm considering taking the plunge and trying out Ruby in earnest[*], but lack of a editor is holding me back. Ideally, I'd like a refactoring browser akin to IntelliJ's excellent IDEA for Java.

There is Ruby Refactoring Browser, but it is version 0.0.3 and only for Emacs. Even so, I installed it but am disappointed by the lack of a ruby-mode.

So I solicit suggestions. Any Ruby on Rails fans with help?

* I like the name Ruby in earnest a lot more than Ant in anger. :-)

Friday, March 04, 2005

Half-bean serendipity

I was struggling to explain to a fellow ex-ThoughtWorker this pattern I had half-formed in my head. The problem was how to construct an immutable java.net.URI when I didn't have all the constructor arguments handy. I was vaguely describing some kind of clever factory that scoops up arguments over time, and spits out an URI when you press the create() button using the constructor which most closely matches the information provided.

Then while looking at clever defense of REST I saw the reference to the half-bean pattern. Serendipity! That is exactly the description I was looking for. I was describing the Half-Bean pattern: the getters were all in the immutable URI, and the setters all in the factory with a factory method to tie them together.

Thursday, March 03, 2005

When the Java three-part expression is not equivalent

What is wrong with this code?

return -1 == endIndex
    ? Collections.emptyMap()
    : makeMap(path.substring(endIndex + 1));

Here's a hint:

private static Map<String, String> makeMap(final String s) {
    final Map<String, String> map = new HashMap<String, String>();

    for (final String pair : split(s, ';')) {
        final int i = pair.indexOf('=');

        if (-1 == i)
            map.put(pair, null);
        else
            map.put(pair.substring(0, i), pair.substring(i + 1));
    }

    return map;
}

Ok, now do you see? What about now:

public Map<String, String> getServiceSpecifiers() {
    final String path = uri.getPath();
    // Ignore service specifier (e.g., ftp)
    final int endIndex = path.indexOf(';');

    return -1 == endIndex
        ? Collections.emptyMap()
        : makeMap(path.substring(endIndex + 1));
}

The return type is Map<String, String>, and Collections.emptyMap() is defined as:

public static final <K,V> Map<K,V> emptyMap() {
    return (Map<K,V>) EMPTY_MAP;
}

So what is really the matter? Last clue; this fixes the problem:

if (-1 == endIndex)
    return Collections.emptyMap();
else
    return makeMap(path.substring(endIndex + 1));

The problem is generics.

The compiler deduces the bounds correctly in return Collections.emptyMap() but not when in the three-part expression (X ? Y : Z). The compiler tries to harmonize the types when evaluating the expression, and this leads to picking the lowest bounds possible, Object rather than String. The expression is then returned, but now it no longer meets the bounds for the method and it is a syntax error.

The IF statement does not have the extra bounds deduction, so reduces the empty map to the bounds of the method exactly.

How annoying.

UPDATE: An anonymous commenter pointed out the correct Java syntax to pull this off:

return -1 == endIndex
    ? Collections.<String, String>emptyMap()
    : makeMap(path.substring(endIndex + 1));

My C++ blinders kept me from considering this possibility; I tried putting the generic specification in several other places in the statement instead, none of which worked. An interesting construction.

UPDATE: Paul Holser pointed out the right name for this construct: the ternary conditional operator.