What's new in Project Lambda this week?
It seems that the Project Lambda developers have conspired to ensure that my blog will always be out of date. I recently wrote about my first impressions from using Project Lambda, based on build b74. Now that I'm writing this, b75 is out and they've renamed the
DoubleBlock, and various
BiBlock interfaces to replace the word Block with Consumer. I suppose that's more consistent with
Supplier, since a
Consumer consumes a value and returns nothing, while a
Supplier takes no input and produces something. It also ties in well with the pipeline metaphor they're using for
Streams (which will still need to wait for a later post, since I got playing with default methods in interfaces this week).
Additionally, they've added several more interfaces to
java.util.function to accommodate
BiFunctions that return primitive values (still to avoid the overhead of boxing, presumably). It's interesting to compare these specialized (and specially-named) interfaces to Scala's use of the
@specialized annotation (discussed, here, for example) to avoid the same problem.
I'm horribly abusing a term that has grown popular in the Scala community for the case where you appear to add functionality to an existing type by providing an implicit view that converts objects of the existing type to objects of the enhanced type. This is referred to as the pimp my library pattern (going back several years, including by Prof. Odersky here). What I'm doing here isn't implicit, but it does show a way that we can use interfaces with default methods to layer functionality onto library types with relatively little ceremony.
In some of my previous posts, (like this one and especially this one), I talked about some nice higher-order functions on collections that most functional programming language environments provide as part of their standard library. The fact is that most of these higher-order functions can be implemented in terms of iterating through elements. Since Java 1.5, the standard collections (except
Map and its implementations) all implement the
Iterable interface. Wouldn't it be great if we could add these higher-order functions as methods on existing collection types? We can't really do that (without compiling our own version of the standard library), but we can inject the
iterator method from the builtin types as a lambda to construct a type that does have this functionality.
Yo dawg, I herd you like iterators
Let's extend the
Iterable interface with an
AugmentedIterable interface that defines additional functionality based on the
As you can see, many of the methods return a new
iterator method (defined by a lambda) delegates to the
iterator method of the original
AugmentedIterable. I put an iterator in your iterator, so you can iterate while you iterate.
Note that this implementation with delegated iterators has the side-effect of making most of these methods lazy (except
foldLeft, which don't produce new
Let's add a quick utility method to construct an
AugmentedIterable from an existing
Iterable, and test our methods:
This still isn't quite as nice as the "pimp my library" pattern, as we still need either the explicit call to
augment to convert our
Collection into an
AugmentedIterable. Furthermore, I didn't really need an interface with default methods to do this, as I believe I could have made
AugmentedIterable an abstract class. Where things get interesting is that we could add more functionality derived from
Iterable in another interface and then mix them together in a new interface that inherits from both. Alternatively, I could create new collection types that extend the built-in types but also add the