Saturday, August 22, 2009

How to Tell Your Co-Workers Have Discovered Functional Programming

Three ways to tell that your co-workers are learning a Functional Programming language at home:

1. You've found the number of .class file in your project quadrupled in the last month.

Here is an output directory with 17 .class files, only 2 of which are not inner classes, most of which are anonymous.



See all those dollar signs indicating inner/anonymous classes? Uh oh, looks like someone discovered shitty lambdas. Your chaos meter should be increasing... will your project be maintainable of it's not idiomatic Java?

2. You've found a class named Pair

public class Pair<T, U> {

private final T left;
private final U right;

public Pair(T left, U right) {
this.left = left;
this.right = right;
}

T getLeft() { return left; }
U getRight() { return right; }

static <T, U> Pair from(T left, U right) {
return new Pair<T, U>(left, right);
}
}
It's not a tuple, but it's about 2/3 of the way there! There's already jfun.util.Pair in JFun and gnu.lists.Pair in Gnu Lists, and now you've got your own too. Hooray. But wait, how will you maintain your code base if the declared name of your data structures don't tell you how it's meant to be used? Chaos... level... rising...

3. You've found a widely implemented one-method highly generic interface

An interface like this has over 100 implementations, many of which are anonymous:
public interface Transformer<T, U> {
U transform(T input);
}
This is equivalent to F in Functional Java and Transformer5 in JConch.

At this point your chaos meter should be off the chart. These functional programmers are surely ruining your system and livelihood. So, I'm hesitant to mention what happens when you combine all of them together:
Transformer identityfunction =
new Transformer<Pair<String, String>, Pair<String, String>>() {
public Pair<String, String> transform(Pair<String, String> input>) {
return input;
}
}
}

Voila, an anonymous function object that uses the Pair class to make a 1-arity method into a 2-arity method, returning multiple values.

These are the trials and tribulations of finding the appropriate use of new programming paradigms in old languages. Looking at version control history, the person that committed all these sins was... me. Will this be the Java code I write in two years time? Certainly not. But which of these example is the growing pains of learning FP and which of these will still be with me in the future?

Comments are open!

10 comments:

Paul Reiners said...

Hi Hamlet,

I like the wide-eyed innocence and enthusiasm of the programmer who has just learned FP trying to use it everywhere he can in Java code at work, even though he might be overdoing it a bit. It's kind of endearing.

I think that the programmer who goes through this phase will be a much better programmer and have his mind expanded quite a lot from becoming fluent in FP. The disheartening thing is that he'll eventually realize that you just can't do FP in a language such as Java that doesn't support higher-order functions. I know that there are workarounds and so on to do FP in Java, but it's not the same thing.

I've given up all (almost) all hope of every getting a job writing Common Lisp, but it would be nice to someday intermingle Clojure code with Java code at work. (Although I hate the "improved" syntax of Clojure.)

Paul

9000 said...

This is hilarious and true.

Once, in a fit of desperation, I wrote private implementations of lambda, fold, map and zip, just to make several pieces of code look "canonical" :) Didn't much help compactness, though: parametric types consume lots of screen space.

Probably it's time to learn some Scala, then.

Hamlet D'Arcy said...

This Spring I implemented the F# List library in Java. I only needed two of the functions, but felt like I needed to do the whole thing in order to feel complete. I never checked it into version control though, I was scared of what everyone else would think.

Mark said...

To me the appeal of fp is less code so doing fp in Java via the methods the author indicates is less than appealing. Besides higher level functions, the things I most like about fp are: syntactic sugar for working with lists and pattern matching (in languages that support it: Scala, Ocaml, SML, Haskell, etc).

Stefan Zobel said...

Hilarious - it's me who has committed all of those sins in the past few months, though, only for a private project.

Diving into some Haskell recently, it is hard to not go overboard with this style in Java though.

I've used the BGGA prototype compiler which makes the syntax much less painful (and can be made fully interoperable at runtime with a standard JRE 6 if you take some care).

But, nevertheless, I wonder how much effort it would require to convince my co-workers that this is the way to go? Certainly not in Java, too much syntax noise (even with BGGA) ...

Obviously, for the JVM, Scala would be the right choice, but then, how to convince them if they don't see a problem with their current programming style at all?

Stefan

Daniel Alexiuc said...

Hamlet, I love reading your posts. It's funny cause it's true.

Praveen said...

This is hilarious and true, Yes you got the true pattern of getting into functional programming trap in Java.
Martin fowler of throughtworks once wrote that he tried this way back in 2005 (of implementing closures with anonymous classes) & finally embraced Ruby.
There are nice libraries that do use these techniques (Generics, anonymous classes) very nicely (Ex: Google collections...) & are here to stay.

BTW what is the problem with many $ signs (anonymous classes) in the jar file.

Dimitris Andreou said...

Well, you gotta love Pair. You can create all acyclic linked-based data structured out of it. Now all we have is a shitty Map.Entry.

Btw, I'm sure everyone enjoys creating hundreds of *named* classes with two fields, to return various combinations of stuff from methods, which can return only one thing.

Hamlet D'Arcy said...

I'm glad everyone thinks this is as funny as me. I had a nice laugh this week as I looked back at my code from this Winter. There are some good ideas in there... but they're not all good!

@Praveen There's no problem with the $ in the JAR file, but seeing all those $ in class file is a smell that the source code (if written in Java) might have a lot of accidental complexity.

Alex Chin said...

4. You find scala-lang.jar or groovy-all.jar appended to your application's classpath. :)