Tuesday, February 05, 2008

Closures Puzzler: Neapolitan Ice Cream

People experience the world in different ways, using different senses. Some people view the world primarily through sight. Do you see what I mean? Some through sound. Do you hear me? Some experience the world only after thought and reflection. Do you know what I mean? Some point out "smells" in code as a way of criticizing its design. This puzzle explores the question of whether people experiencing the same thing through different senses are really experiencing the same thing at all. What is the program's output, and why?

This puzzle uses Java Closures, so if you want to try it you should download the prototype here. You can download the puzzle sources here. Comments on this blog post will not be posted to avoid spoiling the puzzle.

import java.util.*;

enum Color {
    BROWN(Flavor.CHOCOLATE),
    RED(Flavor.STRAWBERRY),
    WHITE(Flavor.VANILLA);
    final Flavor flavor;
    Color(Flavor flavor) {
        this.flavor = flavor;
    }
}

enum Flavor {
    CHOCOLATE(Color.BROWN),
    STRAWBERRY(Color.RED),
    VANILLA(Color.WHITE);
    final Color color;
    Flavor(Color color) {
        this.color = color;
    }
}

class Neapolitan {

    static <T,U> List<U> map(List<T> list, {T=>U} transform) {
        List<U> result = new ArrayList<U>(list.size());
        for (T t : list) {
            result.add(transform.invoke(t));
        }
        return result;
    }

    public static void main(String[] args) {
        List<Color> colors = map(Arrays.asList(Flavor.values()), { Flavor f => f.color });
        System.out.println(colors.equals(Arrays.asList(Color.values())));

        List<Flavor> flavors = map(Arrays.asList(Color.values()), { Color c => c.flavor });
        System.out.println(flavors.equals(Arrays.asList(Flavor.values())));
    }
}

1 comment:

Luc Duponcheel said...

Neal,

just to double-check,

the control invocation syntax only works for methods having as last parameter a restricted closure having a void result type (or, using conversion, for methods having as last parameter a one-method interfaces having a method with void result type), right?

I tried others, and could not get them compiled, but, maybe, it is just my ignorance of the correct syntax.

Luc