Monday, June 9, 2008

The Scala Influence

A while ago, Frank Sommers asked the following:
How Has Functional Programming Influenced Your Coding Style?

If wish I could have replied something then, but I was just starting to learn Scala, and I couldn't.

Now, I'm still just at the beginning of grokking FP, but I can write about how it almost influenced a bit of Java code I had to write the other day at work.

Post update: "I have to use jdk 1.4.2 at work. That's why I am not using generics and all."

I had a list of instances of a certain class, and I wanted to get a list made from the result of invoking a certain method on each instance.

We'll pretend I had a Domino class, and I wanted to invoke the method getPoints() on each instances

Here's how I would have done it in Scala:

class Domino(p: int) {
val points=p
}

val dominoes = List(new Domino(1), new Domino(2), new Domino(3))

val points = dominoes map (_.points)

Let's say it's a bit cryptic in Scala and make it a bit more explicit:
val points = dominoes map (x => x.points)

I'll skip the Java class definition, but it implements the interface WithPoints, which declares the "Integer getPoints()" method .

Now, just look at what I had to code in Java to get the point list:

List points;
for (Iterator iter = Dominoes.iterator(); iter.hasNext();) {
points.add((WithPoints) iter.next().getPoints());
}

Simple really, but I couldn't get over how much neater (to me) it was in Scala.

Now comes the functional programming influence part. It so happens that I had a transformation library at my disposal in my Java project: org.apache.commons.collections

It's not what I really wanted, but I could use some kind of functional programming style with it. And here's the end result:

List dominoes;
CollectionUtils.transform(dominoes, new Transformer() {
public Object transform(Object domino) {
return ((WithPoints) domino).getPoints();
}
});


So there, it's not so bad, except that:
1) It transforms my list instead of returning a new list, which is what I wanted.
2) The imperative version is, in my opinion, clearer.

And so this is how functional programming has (almost, but not quite) influenced my coding style so far.

6 comments:

Al said...

Stuff like this is always held up as fundamentally neater in functional languages, but I really don't see why:

List<Integer> points = Lists.newArrayList();
for (Domino d : dominoes) points.add(d.getPoints());

Plus I get to decide what sort of List implementation I want to use.

If you want a more functional way of doing things in Java, I'd recommend looking at this:
http://code.google.com/p/google-collections/source/browse/trunk/src/com/google/common/collect/Lists.java#304

The Careful Programmer said...

Hi Al,

I can't see why either a "for" construct would be considered neater than a map. The "for" looks more imperative to me but hey, I'm just starting out on the FP road 8)

Thank you so much for the link, I will check it out for sure!

dibblego said...

Hello my careful friend,
A point on your style there; you needn't repeat the call to the Domino constructor, therefore, your Scala would be:

val is = List(1, 2, 3)
val points = is map (new Domino(_).points)

Have you considered looking at Functional Java at http://functionaljava.org/ ?

Your code then looks like this:

list(1, 2, 3).map(new F<Integer, WithPoints>() {
public WithPoints f(Integer i) {
return new Domino(i).points();
}
});

There is a great explanation for why loops are a bad idea out there somewhere (great as in, it dilutes the issue down to an introductory level), but buggered if I can find it.

The Careful Programmer said...

Just a detail I forgot to mention previously: I have to use jdk 1.4.2 at work. so that's why I am not using generics and all.

Although, I could investigate more at home with a recent version of Java and the libraries mentioned in the comments.

Bhaskar said...

I am not certain I understand what you are trying to say, I assume it is just ignorance or rather poor Java style on your part

You mention:

Now, just look at what I had to code in Java to get the point list:

List points;
for (Iterator iter = Dominoes.iterator(); iter.hasNext();) {
points.add((WithPoints) iter.next().getPoints());
}

Yeah, ugly, unless you were restricted by the java version you were using, not using a for-each loop or generics to avoid the explicit iterator and type casting is just poor quality code.

You then demonstrate the following

List dominoes;
CollectionUtils.transform(dominoes, new Transformer() {
public Object transform(Object domino) {
return ((WithPoints) domino).getPoints();
}
});

concluding ...

So there, it's not so bad, except that:
1) It transforms my list instead of returning a new list, which is what I wanted.
2) The imperative version is, in my opinion, clearer.

if you had really read the documentation on collection utils, you would have found the method "collect" which

Returns:
the transformed result (new list)


Seems like a deliberate attempt to write obfuscated code to come to a conclusion that you had decided on prior to writing any code. Clearly drinking the cool aid without knowing what is put into it. Rather special...

The Careful Programmer said...

Hello Bhaskar,

Thank you for your comment.

Indeed, on the comment just before yours, I do mention that:
"Just a detail I forgot to mention previously: I have to use jdk 1.4.2 at work. so that's why I am not using generics and all."

About the "collect" function, thank your for the pointer. I had skimmed through the documentation too quickly.

I really did not set out to write obfuscated code. I was just honestly documenting an attempt to try out a more functional style in java 1.4. No doubt a more experienced person than me would have gotten a better result.

That is why I am blogging, to share my experience, hopefully helping others (or me!), generating interesting discussions and getting useful feedback 8)

I'm no Java guru, just a guy on the road to better my craft.