MatchError

суббота, 15 марта 2014 г.

Today I found a good FP library which is called totallylazy. This library has a lot of great features like persistent collections, options and streams (they call it Computation), but it also has a very good feature, which makes it possible to write multimethods in Java. I think, multiple dispatch is a great tool that makes code much more concise and cleaner. This is how it looks:

public String
collide(Object obj1, Object obj2) {

returnnew
multi(){}.<String> methodOption(obj1, obj2).getOrThrow(

new
IllegalArgumentException("No method
found for args: " +

obj1.getClass() + ", " + obj2.getClass()));

}

@multimethod

public String collide(Asteroid asteroid,
Spaceship spaceship) {

return"Asteroid hits spaceship";

}

@multimethod

public String collide(Asteroid asteroid,
Asteroid asteroid2) {

return"Asteroid hits another asteroid";

}

@multimethod

public String collide(Spaceship spaceship,
Asteroid asteroid) {

return"Spaceship hits asteroid";

}

@multimethod

public String collide(Spaceship spaceship,
Spaceship spaceship2) {

return"Spaceship hits another spaceship";

}

This is a classis example of multiple dispatch taken from Wiki. So if you pass two objects to the collide method, the method with most specific parameter types will be picked:

Of course, this uses internally some sort of reflection and this is not as fast as static method linking. But since the famous rule says "Avoid premature optimization", you should not be afraid to write such code.

This is sometimes called a loan pattern which is widely used in Scala. I use using as a method name, because try is a reserved keyword in Java and Xtend. The following example shows how to use the using statement:

importstatic org.example.xtend.Using.*

val text = using(new FileReader('file.txt')) [

val buf = CharBuffer::allocate(1024)

// this is just an example

it.read(buf)

buf.rewind

buf.toString

]

println(text)

One can use it keyword to refer to a passed instance of Closeable.

The nice feature is that using can also return a value. So, "Everything is an expression" principle works here as well.