In my last post regarding the programming language Xtend I showed you IMHO a better version of the famous reduce function. Whose default implementation is quite crippled. Now after picking up the work on the project where I have to use Java (and try to avoid it with Xtend), I tried to become productive with the language and its features. To incorporate my version of reduce I made a utilities class holding it. As well as an again modified version of reduce, where you don’t have to specify an initial value. Now I could use those through the “import static extension” mechanism.
While plodding along I stumbled over a point I don’t like. It is nice to have those collections enriching extension methods available, but their applicability is quite restricted compared with the rich collection interface others (for example Smalltalk) provide. For me the basic problem is, when you call one of those functions you provide an anonymous function that gets called for each element. It is just that. You don’t have access to the context of this anonymous functions creation. The Xtend blocks are not closures, only lambda expressions. This Stackoverflow question, better its answer, explains the difference quite decent. To explain what that means in practice consider the following gist:
In the first function I’m trying to return from within the block body, assuming I’m breaking the loop and return the surrounding method. It is the naive approach one would take if “forEach” would be essentially the same as a Java for loop. The compiler forbids it. The second function defines a local variable and tries to reassign it with a different value from within the block. The compiler forbids it, stating that, when in a block, you can only access variables that reside outside that block if they are final (vals in Xtend parlance). And now? Revert to a for or while loop. Abuse some other extension function like my version of reduce? Nothing felt really good.
I decide to roll my own version of “forEach”. Giving it a return value and the functions user a handle to break the usual control flow. The following gists display the code of the utility function and a necessary helper / trigger class:
Before I waste many words, here follows a gist that shows you how you can use this extension method.
By the way I didn’t like the square bracket notation for blocks in the first place, because of its unnecessary derivation of known syntax for basically the same thing (a function or method body). But now it even feels misleading. Because everyone with Smalltalk knowledge assumes that they are true closures. And because the creators of Xtend chose consciously the Smalltalk notation for blocks, they provoke that analogy.