Drinking the kool aid

Ahh yes I have indeed been partaking of quite a large volume of functional kool-aid lately, its quite scary. This week I’ve mostly just been doing lisp, lisp, lisp, and more lisp. In fact I don’t think I’ve touched Perl this whole week long, which is weird.

Still its been a good time, I’ve grappled with CLOS (let me fetch my crack pipe) and won the functionality I wanted, I’ve started to do more experimentation with some of the finer points of the whole style of coding itself.

For example, let me for a moment take you on a waffly journey around my criteria system (EDIT: Its probably worth knowing that I’m writing software that searches a graph of nodes and looks for suitable paths between any two nodes), for judging if a path has the right metrics/length/whatever to be acceptable.

We start with (make-criteria-pointer), this takes the name of a function and the arguments to pass to it, and returns a pointer to a function that takes a single path and runs the original function/args against it, returning true or false.

While that sounds a bit confusing, let me break it down for you, I’ve got a function for juding if a list is too long, which looks like this:

(defun max-length-p (path n)
  "Accepts a list-of-nodes (path) and an length (n) and returns T(rue) if the list is shorter than the length"
  (if (<= (list-length path) n)

So if I run

(make-criteria-pointer 'max-length-p 5)

it returns a pointer to a new anonymous function that looks like this:

(lambda (x)
  (max-length-p x 5))

i.e. it always checks to see if x is longer than 5 items long.

Now this doesn’t seem to be too useful, however there are simple ways to build a list of these function pointers, so if I do the following:

;; Maximum path length is 5
(new-criteria (make-criteria-pointer 'max-length-p 5))

;; Path must include one of the nodes foo,bar or baz
(new-criteria (make-criteria-pointer 'path-must-include-p '(foo bar baz)))

;; The minimum level of trust between nodes is 10
(new-criteria (make-criteria-pointer 'metric-p '("trust" 10)))

Then new-criteria keeps adding these function pointers to a list (called *criteria*, although you can tell it to add them to another list), and now if you say:

(check-path-p path-to-check *criteria*)

It will go through the list stored in *criteria*, passing path-to-check to each one of these functions and if the list doesn’t pass muster then check-path-p just returns false.

metric-p is also a generic checker of numeric (or other) values on links in the path, and so you can make it do crazy shit like this:

(metric-p path-to-check 
          '("bananas" "plenty") 
          :test #'(lambda (x y) (check-number-of-bananas x y)))

And it’ll dig up the “bananas” value about each link in path-to-check and instead of just checking this value numerically it will pass x (the value from each link) and y (“plenty”) into the newly defined function (lambda is an anonymous function), which will call check-number-of-bananas on these two values to determine if the link has “plenty” of bananas.

Now I’m sure there are plenty of other ways of doing systems like this but frankly Lisp can be deeply satisfying to write this kind of thing in. Once I got the last bits of this system in place this evening I left work pondering ways to improve it for speed or functionality, and have a list of three/four more things it could do by the end of Monday to complete it.

Just so damn shiny!

3 thoughts on “Drinking the kool aid

  1. darius_of_lancs

    OK, OK, I’ve been mulling this for days… I humbly beg a question?

    Why in the name of all that is holy are you using LISP w/ CLOS? A decent OO language with a well defined interface definition and a decent collection class (vector, map, or even stack if you are so inclined) would have been easier and more parible… ;)

    May I recommend C#…

    1. Anonymous

      Because the problem (searching a graph) is easily done in LISP, and because with CLOS you don’t have to write a number of silly wrappers around lists, and its nicer than using structures for everything.

      Besides, its a good oppertunity to learn the language, which I recommend for its pretty nature and the fact it makes your mind glow.

      C# isn’t a bad language in and of itself, but I just can’t be arsed with it (how portable is it comparsed with LISP?), the other “decent” OO languages are things like Java (not too bad these days but I dislike the syntax and enforced OO nature), C++ (Please god no, I don’t need to spend time fucking around with memory allocation) or Python (which is a foulness, lets be honest).

      I suppose I could have gone with something really screwy and OO like Ruby… but thats halfway to writing it in LISP anyway :)


Leave a Reply