Monday, May 3, 2010

I hate looping / iterating / eaching

I really hate looping. I mean I really hate looping. Why is that you ask? Because most of the time our looping is not looping. You're filtering, you're transforming or you're calculating, you're not looping. Looping is a means to an end. You loop to perform those actions. But syntactically it's quite common in many languages to see something like: for (blah in blahs) do some filtering / transforming / what ever. Why does the statement "for (blah in blahs)" come first? why isn't it blahs.filter(some predicate) or filter(blahs predicate) or blahs.transform(some stuff) or really so many other options. Why isn't the intent of transforming / filtering / calculating brought to the forefront?

I love clojure's solutions to the issue: filter, map, reduce. You can get rid of 99% of all your looping and describe better what you're trying to do. I've been trying this in java (I know I know it's a mistake)... with google collections. I mean great they have filter, transform, this will look great. It really doesn't:

List filtered = new ArrayList( Collections2.filter(foos, new Predicate() { @Override public boolean apply(Foo foo) { return foo.isBar() && foo.isBaz(); } }));
List filtered = new ArrayList(); for (Foo foo : foos) { if (foo.isBar() && foo.isBaz()) { filtered.add(foo); } }

Well fine I'm maintaining intent (I guess) by using a filter method and a predicate, but the whole filter mechanism gets completely lost in all the boiler plate java cruft. I love that I can just implement an apply method, highlighting the boolean expression, and the magic is done for me, but I need so much more code to get my work done. Sure I'm removing duplication of looping (which is nice) but at such a legibility cost. Maybe I'll get used to all the crazy syntax, and it will just fade into the background, but for the moment I'm really doubting it.


ekerwin said...

Any reason it needs to be in pure java? Groovy looks pretty decent if you're stuck on a JVM.

List filtered = foos.findAll{ e -> e.isBar() && e.isBaz() }

Zachary D. Shaw said...

no question a lot of languages either have it right or have the flexibility to get it right, Java doesn't on either account. They should allow monkey patches in java, and let me add: filter, map and reduce to collections :o

Brendan Miller said...

Java is terrible... just terrible.

I like python's approach, which provides special syntax for mapping:

squared_list = [x * x for x in list]


filtered_list = [x for x in list if x > 2]

Also, you can compute your results lazily with generators:

squared_iterator = (x * x for x in list)

Rob Park said...

In Java (agreed, big mistake)... do you find that you sometimes try to bury the ceremony in another class? I do... just to try to reduce the noise.

List filtered = new ArrayList(Collections2.filter(foos, new IsBarBazPredicate()));


Web Statistics