Yardena has posted 2 posts at DZone. You can read more from them at their website. View Full User Profile

Functional Programming: Static Methods as Function Objects

05.02.2008
| 4734 views |
  • submit to reddit

In one of my earlier explorations I described a policy object created by "functional style programming" in Java. The basic idea is to make methods into Function and Predicate objects and then composite the logic from these building blocks. The problem though was that the policy implementation looked alien to Java. To re-cap: I wanted to invoke a different function based on the class of the object - classical multi-dispatch with a single argument.

So inspired by extension methods idea I added a new mechanism to define properties (and functions in general) - via static methods. You define a bunch of static methods with the same name (or appropriately annotated) like this:

static int size(Collection c) {
return c.size();
}
static int size(Map map) {
return map.size();
}
static int size(Object obj) {
return (obj.getClass().isArray() ? Array.getLength(obj) : 1);
}
static int size() {
return 0;
}

Now assuming I have a property declaration

Property<Object,Integer> size = new Property<Object,Integer>() {};

The underlying implementation of the size.of(object) would be a "policy" (composite function) dispatching to one of the static methods according to run-time type of the object. So that size.of("foo") is 1, size.of(Arrays.asList("a","b","c")) is 3 and size.of(null) is 0.

There are couple of issues though.

Issue #1: automatically ordering the rules. Now when rules are not added manually, I should be careful to test for more specific class first. The solution is to calculate a distance between two classes and always look for a best match - basically same algorithm javac uses when choosing methods at compile-time. This isn't fully unambiguous though: if class C implements 2 interfaces A and B, having different implementations of size(A) and size(B) would put me into a dilemma which one to choose for size(C). Javac in such a case reports an error - thanks to Java being statically typed. But once I make it a run-time decision the only logical solution is to report an error at run-time. To make the problem less acute, I could add an annotation that controls ordering of the methods.

Issue #2: this is less generic than a general predicate-based policy - it is limited to "instanceof" predicate. One of the policies I use internally in the properties project is reflectively invoke getFoo() if the class has a "getFoo" method. This isn't possible with static methods.

Issue #3: reflection
. It's not really a problem, but rather an enhancement I want to make: instead of using reflection I could generate the functions at compile-time with APT, like Bruce Chapman does here. This is one of my next adventures, which I will hopefully describe in a future post.
3
Your rating: None Average: 3 (2 votes)
Published at DZone with permission of its author, Yardena Why.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

David Voo replied on Sat, 2008/05/03 - 2:12am

Hi there,

Forgive me that I do not understand this article, someone care to explain to Java rookie here?

Thanks

McFarland replied on Mon, 2008/05/05 - 10:47am

Wouldn't it just be easier to use Scala, which gives you clean functional code and can be used interchangeably with Java?

Steven Baker replied on Mon, 2008/05/05 - 10:20pm in response to: McFarland

no, because this is javalobby, not scalalobby.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.