Now that BHurt has done a nice job talking about why Laziness is cool, I’ve got a bit of an ax to grind.
The problem I have is that Java all but completely fails to be lazy, which is a shame considering how useful the trick is.
The Sun team themselves seem to be of the opinion that functional programming generally isn’t something one should be doing. The core library has a complete lack of functional support, and so those who want to use functional coding methods are delegated down to defining lots of interfaces and inner classes, which really clutters up the API and looks ugly. C# did a somewhat nicer job by basically stealing C++’s “function pointer” concept, and I’d like to see Java implement it eventually.
The bigger issue is that even in the Jakarta Commons framework, there is no implementation as Brian described it. What they have as a “LazyList” in Jakarta Commons-Collections isn’t terribly useful: instead of generating a “next object” like the theoretical lazy list does, it generates an object based on no input (not even the index of the array!). There isn’t a way to wrap a List in a series of lazilly-evaluated (get-time) transforms: the TransformedList is all put-time. There is no “next-function-based” Iterator. The two major useful pieces of lazy functionality they do have is the TransformIterator (which does enable you to chain transforms at get-time) and the LazyMap (which enables transformation-based lazy generation).
Now, there is work that can be done to extend the Commons-Collections to implement that kind of functionality, but I haven’t even begun to test the waters to see if it would be something the core development team would be willing to accept. I’m a bit busy devoting my free time elsewhere, so if someone else would pick up this ball and run with it, I’d love to see it in. Otherwise, it’s something I’ll get around to whenever I get back to spending my limited free time on Java work.
10 Comments
Two answers:
Closures
java.lang.Iterable
I’m not sure what you’re getting at.
Sure, Java5 has finally introduced
foreach, but how does the Iterable provide any of the true lazy list functionality?Closures are certainly a nod towards functional development, but even they are very limited in Java (require final variables for anything enclosed, must be full-fledged classes) — and they don’t provide lazy functionality either.
Oh, and just to be clear — I don’t really consider “foreach” to be a functional construct. I consider it an imperative syntax hack which is functional in flavor.
By closures I mean true closures – http://www.javac.com/ – not those inner-class closure wannabes. I’m hoping they’ll make it into JDK7.
Iterable and its companion Iterator use the next() method for generating values, and are sometimes used to represent lazy lists.
What’s that Javac link supposed to be for? Got a JSR for true closures?
See BHurt’s post (linked in my original post) on why a true lazy list is better than just an Iterator — he addresses it pretty directly.
But, yes, were I to want to hand-roll a lazy list, I would probably do something as follows:
* Create an Iterator based on a Transformer (provided the previous element? The index?)
* Create a List based on an Iterator which doesn’t force the exhaustion of the Iterator immediately (although some Collection methods — not least List#size() — would pretty much require it to do so).
* Create get-time alternatives to TransformedList and PredicatedList so that the wrapper design pattern could be applied to process lists.
Were I to want some of the lazy functionality cheaper, I could just use TransformIterator, but then I don’t have a List to work with, I have an Iterator, with the ensuing limited API.
Sorry, the link should be
http://www.javac.info/
My brain reads those closures precisely backwards, because of the syntax of Ocaml, but that’s not something I’d expect Java developers to care about. I am surprised, though, that they didn’t pick up something like C#’s function pointer syntax — that’s a lot more concise.
That all said, it’d be kinda nice to have something like this in play.
Candide: the only reason that java.util.Iterator might not be thought of as a lazy list (according to BHurt) is that the map/reduce/transform (etc) operations take List instead of Iterator, and don’t operate lazily… but wait a sec, those operations don’t exist in Java yet! We’ll be adding them (I hope) along with closures. So when we add them we can ensure that they (or versions of them) operate properly on lazy data structures, returning lazy data structures in return.
Thus my original answer.
15 years or so ago, when OO was just starting to become popular, a programmer aquiantance of mine stated that he hated OO programs, because they were impossible to follow the flow of control in. This was especially the case in OO programs written in procedural languages (yes, Virginia, you can write OO programs in C, I have), where the implementation details can obscure the fundamental patterns. An experienced OO coder would immediately start recognizing the patterns- this is inheritance, that’s a virtual function, this whole structure is actually a class, specifically it’s a decorator, etc. But he didn’t know the design patterns, and thus OO programming to him was an undifferentiated mess of function pointers and unmaintainable code.
Now, there’s a point to this story, and the point is this: if the paradigm isn’t understood, the likelyhood is that the program won’t be understood either, nor appreciated. Nor maintained.
Nothing I’m describing here is actually that hard to implement in Java. OK, there are some rought edges, and implementation details will show through, but technically it’s not that hard. But ask yourself this question: if you implemented a lazily evaluated list, with lazily evaluated maps and filters etc., and then implemented Newton’s method as an infinite list- what would the average Java programmer’s response be? Remember that this design pattern in unusual for Ocaml programmers (although it’d be medium-obvious for Haskell programmers, I think).
To Gafter:
Right — so Java’s completely failed to be lazy, but there’s some people out there who would like to introduce things that would make it easier to be lazy. Granted. That doesn’t change the fact that it’s just fallen apart right now.
Maybe someday it’ll catch up — but my guess is that you won’t really see it until F#, Ocaml, or Haskell break their way into business. We may be lucky, and Sun may be looking at some of the quasi-functional stuff in Ruby, but I doubt that.
To BHurt:
Yeah, I’ve personally encountered that situation. I actually feel kind of bad, because some of the stuff that I treat as natural (e.g.) the people at my last contract are completely baffled by. They keep saying things like “He should have a Ph.D. for this kind of stuff.”, which is far from true — it’s pretty clear what’s going on, as long as you’re used to functional styles of development.
One Trackback
[...] If you’re not sure what I’m babbling about, check out this post for an introduction to lazy lists in their natural environment, and this post for my railing about Java’s lack of lazy lists. You can also bookmark this on del.icio.us or check the cosmos [...]