Saturday, 21 March 2015

Late binding

I’ve just implemented support for late binding in the EnumJ library. This paves the way for enumerator serialization which, in turn, will make possible remote and/or distributed enumerations.

The problem

Usually, when we enumerate, we know what we enumerate upon. This is materialized in the EnumJ library by the Enumerator.of() kind of methods. They receive an iterator, iterable, enumeration, stream or spliterator as parameter.

But what if, at the time of pipeline construction, we don’t have the source ready? In this case we have the option to provide the source of enumeration lazily and the methods Enumerator.ofLazyIterator(), Enumerator.ofLazyIterable(), … etc., give us some form of late-binding.

It gets more complicated: what if the source of information is completely unknown when we build up the pipeline? Lazy inputs don’t help because the input supplier must know what iterator to supply lazily.

Here’s where late binding comes into play.

The solution

The EnumJ library now exposes a LateBindingEnumerator<E> class which implements Enumerator<E> and has two more methods:

  • void bind(Iterator<? extends E> source) that binds the enumerator to a source.
  • Optional<Iterator<E>> binding() that returns the iterator bound to the current enumerator, if any.

The Enumerator<E> interface has been extended with the Enumerator.ofLateBinding(Class<E>) static method which builds a new LateBindingEnumerator<E> instance.

Usage

Using late binding is straightforward:

LateBindingEnumerator<String> someStrings = Enumerator.ofLateBinding(String.class);
Enumerator<String> upperAndDouble = someStrings.map(s -> s.toUpperCase()).map(s -> s + s);

The sequence above produces a fully fledged pipeline that will work upon any iterator returning String instances. All we need to do is to bind someStrings and use the pipeline:

someStrings.bind(Enumerator.on("first", "second", "third"));
upperAndDouble.forEach(s -> System.out.println(s));

This will print:

FIRSTFIRST
SECONDSECOND
THIRDTHIRD

Support for serialization

The purpose of late binding is obvious: to support serialization of enumerating pipelines.

If we don’t have late binding, serializing an enumerating pipeline would imply serializing the entire origin – which can be prohibitively large. Late binding enumerators avoid this: the pipeline uses a late binding enumerator as its source.

When de-serialized, the pipeline works properly if the late-binding enumerator gets bound to the appropriate source of data after de-serialization.

JavaDoc

The location for the updated Java docs is the same.

No comments:

Post a Comment