Friday, January 9, 2009

Streams

So, to lead into this: Scala, despite being a quasi-functional language, doesn't have much laziness support. There is a lazy keyword, and you can have lazy arguments, but by default everything is eager including 99% of the collection functions. Why is this a problem? Because I've changed my mind and decided that instead of returning the first answer to my question, I want all possible answers; except I don't want to pay the price of computing all possible answers until I actually need them, ergo I want a lazy collection. But in order to get my lazy collection, I have to convert my entire API over to Streams, which is the one token lazy sequence in the entire Scala standard library. And it's a hassle!
Clojure, on the other hand, has almost everything set to lazy. Many was the time that I thought: "Hmmm... this would be so much more convenient if I were using Clojure." For whatever reason, I did not listen to myself.
But it's not too late. Perhaps I will make a hybrid project of Scala and Clojure. I'm not sure how difficult that would be, or even if it is possible at all. Maybe it'll be too ugly. Alternatively I could just convert entirely over to Clojure... but that seems like wasted effort; I don't want to keep reimplementing projects in different languages -- throws away too much work. Lastly I could just bite the bullet and use Scala's damn nasty Stream crap, and live with a duplicated API for streams and not-streams.
Something to ponder.

Wednesday, January 7, 2009

Constraints ReReVisited

My wonderful and glorious, and long_windedly_titled Finite-Domain-Constraint-Satisfaction-Library, now solves Sudoku and sundry other Finite-Domain-Constraint-Satisfaction-Problems. Special thanks to Peter Norvig and the wonderful "AI: A Modern Approach" book. Also special thanks to the Cream constraint library (which was the original inspiration) and the Oz/Mozart language/library.
For those of you who haven't been following the progress of my library, it's written in Scala, and clocks in at just over 2000 loc; thats 1000 of library code plus 1000 lines of testing code -- which was essential because I refactored this thing so many times... if I hadn't had the tests I would have never gotten it working.
The future of the library is bright. There are more things to add and some improvements to make; however, its core parts seem to be feature complete. It uses the AC-3 algorithm to do the constraint propagation, and a simple backtracking search to solve the problems (if constraint propagation by itself doesn't do the trick). It maintains arc-consistency as it searches, and the next-variable-picker-algorithm, the constraint-propogation-algorithm, and the search-algorithm are all swappable. I'll be implementing more algorithms as time goes on, so the user may select the best strategy for solving their particular problem. Right now next-variables are selected using the Most-Restricted-Variable strategy, but for completeness I definitely need to add more options.
Oh, and special thanks to the Eular Project, which got me off on this constraints tangent in the first place.