Thursday, July 27, 2006

Closures

As a novice in the ways of Lisp I'm constantly being reminded just how cool it is. In this particular case, I was working on some code for sending messages to our agent, and needed to provide a sync version of an async send-message. We do something similar in C++ and ended up with a special synchronous handler class, and about half a page of code. I was approaching the same issue in our new Lisp backend with some trepidation since I knew I was going to need to use some mutexes and condition variables, which I had never used in Lisp before. Including the time it took to actually read the docs and get reminders about how Lisp works from Jasko, I had something working in a matter of minutes:

(defmethod send-message-sync ((client client) command)
(let ((condition (make-waitqueue))
(lock (make-mutex :name "sync lock"))
(result nil))
(with-mutex (lock)
(send-message client command
#'(lambda (obj &rest args)
(with-mutex (lock)
(setf result args)
(condition-notify condition))))
(condition-wait condition lock))
result))

That little lambda tucked away in there closes around a lock, condition variable and result—all waiting for our eventual message return. It is not that I can pass the value of result into the lambda that is so powerful. But rather, when the lambda assigns a value to result and fires off the condition variable in whatever far-off place it ends up, back in the thread where I started and am patiently waiting my result gets the new value.

When you read about closures in texts on Lisp they seem so pedestrian. "Yeah, but I can do that with a functor in C++, pointers, references, blah, blah, blah." Then, you actually use them to solve a real problem, and the lightbulb goes off.

0 Comments:

Post a Comment

<< Home