Declarative programming: a Range type for Java

Scala got it and of course all the other hip languages these days like Ruby and Groovy got it, too. Talking about a build-in type for Ranges, some praise for its easy to apply and readable Declarations, a demonstration of a sound declarative Style.

For example, if we want to print all even numbers in a Range between 11 and 22 in Ruby, we simply could apply a literal form like this:

for number in 11..22
 puts "#{number} is even" if number%2 == 0
end

Scala goes another way by ‘enhancing’ Ints to RichInts (using an implicit conversion), providing an until() method that acts as a factory method for Ranges (with an exlcuding upper bound):

 ( 11 until 22 ).foreach{ number => if( number%2 == 0 ) println( number + " is even" ) }

Having heard some of the paeans due to such concise and declarative style (and some side blows because of Java’s lack in this field) recently, i’ll show you that Java must not stand behind! In the following sections i’ll give you a first version on how to build a Range type and use it in a concise, readable way even in Java. This solution won’t be complete, but meaningful enough to get the overall idea.
And – i have to announce a little warning at this point: the following sections will offer quite a bit source code. We’re gonna take a deeper look on what’s going on under the hood – and of course you’re welcome …

In the Range

First of all, we have to be clear about some prerequisites for Ranges. One of the most mandatory ones is the idea of an order (i.e. a natural order of all elements of a type) so we can decide if a given value of a specific type is within a certain Range or not. In Java, such an order is implicit given for all types which implement Comparable. Now we could go for a first version of our Range type, where we decide if a given Range contains a specific value simply by delegating the question to the implicit given order of comparable types:

package types;

import java.util.Iterator;

public class Range<T extends Comparable>{

	private T from = null;
	private T to = null;

	public Range( T start, T end ){
		this.from = start;
		this.to = end;
	}

	public boolean contains( T value ){
		return
			from.compareTo( value ) <= 0 &&
			to.compareTo( value ) >= 0;
	}
}

In order to create a Range in a more declarative style, we’ll again put a simple factory method to our collection class (see the previous posts):

package literal;

import types.Range;

public class collection {
...
	public static <S extends Comparable> Range<S> Range( S from, S to ){
		return new Range( from, to );
	}

	public static Date Date( String date ){
		try {
			return DateFormat.getDateInstance().parse( date );
		}
		catch (ParseException e) {
			throw new RuntimeException( e );
		}
	}
}

Now it’s easy to declare and use a Range in a declarative style. Note, that we could create Ranges for arbitrary types as long as they implement Comparable:

import static literal.collection.Range;
import static literal.collection.Date;
...
	assertTrue( Range( 11, 22 ).contains( 17 ) );
	assertFalse( Range( 11, 22 ).contains( 28 );

	assertTrue( Range( Date( "11.04.2005" ), Date( "27.09.2007" ) ).contains( Date( "23.07.2006" ) ) );

	assertTrue( Range( 'a', 'z' ).contains( 'q' ) );

I count on you

Knowing if a certain value is within a given Range is nice, but looking at the examples for Ruby or Scala at the beginning of this post shows another important feature – iterating over all elements of a Range.
Now we have a little problem at first sight: Since we don’t know the exact type of the Range’s elements at design time (they are generic, the only thing we know is that they are comparable), we can’t increment the values in a uniform way: incrementing numbers and incrementing dates (or chars) is at least – different.

One solution (surely not THE solution) is to rely on a Strategy that knows how to increment the values of a certain type:

package types;

public interface Sequence<T> {

	public T value();

	public Sequence<T> next();

	public Sequence<T> previous();
}

Now we could implement a concrete Strategy for every type that we want to increment (or decrement) this way:

package types.sequence;

import types.Sequence;

public class IntegerSequence implements Sequence<Integer>{

	Integer value = null;

	public IntegerSequence( Integer value ){
		this.value = value;
	}

	public Integer value(){
		return value;
	}

	public Sequence<Integer> next() {
		return new IntegerSequence( value + 1 );
	}

	public Sequence<Integer> previous() {
		return new IntegerSequence( value - 1 );
	}
}
...
public class CharacterSequence implements Sequence<Character>{
...
	public Sequence<Character> next() {
		return new CharacterSequence( (char) ( ( (int) value) + 1 ) );
	}
}
...
public class DateSequence implements Sequence<Date>{
...
	public Sequence<Date> next() {

		GregorianCalendar cal = new GregorianCalendar(  );
		cal.setTime( value );
		cal.add( Calendar.DATE , 1 );

		return new DateSequence( cal.getTime() );
	}
...
}


One thing left is to provide a RangeIterator that delegates the incrementation of values to the approriate Sequence.
You’ll see, that the given solution only iterates over a Range by incrementing values (so we only should declare Ranges in ascending order). It’s quite easy to provide a more flexible solution that could also iterate a given Range in descending order by decrementing the values of a Range – i’ll left that as a little exercise for you :o)

public class RangeIterator implements Iterator<T>{

	private Sequence<T> sequence = null;
	private T end = null;

	public RangeIterator( Sequence<T> sequence, T end ){
		this.sequence = sequence;
		this.end = end;
	}

	public boolean hasNext() {
		return sequence.value().compareTo( end ) <= 0;
	}

	public T next() {
		 T value = sequence.value();
		sequence = sequence.next();
		return value;
	}

	public void remove() {
		// not implemented
	}
}

Now, finding the right Sequence is a bit tricky. In our solution we’ll use reflection while relying on some conventions and name patterns (you surely could come up with some other Strategies for detecting the right Sequence):

...
public class Range<T extends Comparable> implements Iterable<T>{
...
	public Iterator<T> iterator() {

		Sequence<T> sequence = null;

		String className = "types.sequence." + from.getClass().getSimpleName() + "Sequence";
		try {
			Class clazz = Class.forName( className );

			sequence = (Sequence<T>) clazz.getDeclaredConstructor( from.getClass() ).newInstance( from );

		}
		catch (Exception e) {
			throw new RuntimeException( "No Sequence found for type " + from.getClass() );
		}

		return new RangeIterator( sequence, to );
	}
}

As you have seen, we rely on a convention here: all Sequences share a common name pattern
<Simple TypeName>Sequence
and have to reside in a package named types.sequence. This simple solution will cause of course some naming conflicts if we want to add some more Sequences. Another concern might be writing to much Sequences (for every single type) – this could be solved by a more general solution using inheritance trees when detecting the right sequence for a given type.
Even if the given solution is a bit weak here, i think you get the general idea.

Now Java’s hip, too (concerning Ranges)

At present, we could easily come up with a similar solution like the given ones for Scala or Ruby at the beginning of this entry. Since Range implements Iterable, we’re even able to apply Ranges in a for loop:

for( int number : Range( 11, 22 ) ){
	if( number%2 == 0 ) println( number + " is even" );
}

In the end – a Range Builder

If we additionally want to offer a similar style for declaring Ranges like in Scala (even Ruby offers a similar method upto() for declaring Ranges in an additional way), we could provide a Range Builder as an extra:

public static <T extends Comparable> RangeBuilder<T> from( T start ){
	return new RangeBuilder<T>( start );
}

public class RangeBuilder<T extends Comparable>{
	private T start;

	public RangeBuilder( T start ){
		this.start = start;
	}

	public Range<T> upto( T end ){
			return new Range<T>( start, end );
	}
}

Given the Builder and the relating factory method, we now are able to declare a Range like this:

for( Date date : from( Date( "1.1.2000" ) ).upto( Date( "1.2.2000" ) ) ){
	println( date );
}

Another Area – same conclusion

Again – like in the previous post – we might come to the same conclusion: Java’s not on the ropes.
Sure, it might be some work to produce a full blown range type, even with those whistle and bells for creating Ranges in a more declarative style. But this effort is a one-timer and worth the commitment since you’ll get a generic type that’s applicable in a wide range of use cases.

Advertisements
Posted in java. 12 Comments »

12 Responses to “Declarative programming: a Range type for Java”

  1. Types Of Exercise Says:

    […] Declarative programming: a Range type for Java […]

  2. Mike Says:

    And of course, there’s always a second way of doing it in Ruby:

    11.upto(22).each { |i| puts “#{i} is even” if i%2==0 }

    You can define new methods for int, too thanks to Ruby’s open classes. Scala just copies from it.

  3. Mike Says:

    Or, to do it in the exact same way Scala does it:

    (11..22).each { |number| if (number%2 == 0) puts “#{i} is even” }

  4. Kieron Says:

    Great stuff! Thanks for that. Now I just need to find an excuse to use it… 🙂

  5. Raphael Says:

    (11.. (number%2 == 0) puts “#{number} is even” }

    same in groovy

  6. Raphael Says:

    (11.. < = 22)

  7. Tagging the Web Daily 08/07/2010 « PAB Skunkworks Weblog Says:

    […] Declarative programming: a Range type for Java « brain driven development <span class="“> – Annotated […]

  8. mukul Says:

    i wanna to b member of java range.

  9. www.bug-hotel.org Says:

    Modi, while attending a business meeting on Pv Cell
    Labview energy here, said that the tenders are finalized but it would be helpful.
    There’s a lack of pricing power on the other hand, coming from natural resources such as sunlight, wind, geothermal, biogas, biomass, hydro, carbon capture and greater energy efficiency. On the operation side of the world in the development of Pv Cell Labview generation in Northern Ireland has been approved by the Senate.

  10. Clash of Clans Gem Hack Says:

    Please let me know if you’re looking for a article author for your weblog. You have some really good posts and I feel I would be a good asset. If you ever want to take some of the load off, I’d absolutely love to write some content for
    your blog in exchange for a link back to mine. Please shoot me an email
    if interested. Many thanks!

  11. Clash of Clans Hack No Jailbreak Says:

    Hmm is anyone else encountering problems with the images on this blog loading?
    I’m trying to figure out if its a problem on my end or if it’s the blog.
    Any suggestions would be greatly appreciated.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: