Roger Peppe, long time Inferno hacker, has released a Common Lisp version
of CSP: Communicating Sequential Processes (a la Plan 9). The Cliki page
is here http://www.cliki.net/csp. As a long time Plan 9 fan, I was
excited to see it, and thought I would post a couple of examples.
CSP synchronizes on channel communication. In the following examples:
? is the receive operator,
! is the send operator,
alt is the choice operator,
and spawn does about what you think it would do.
The first example is a simulation ui event handling:
;;;adapted from the squeak paper: http://research.microsoft.com/Users/luca/Papers/Squeak.pdf
(defparameter *dn* (chan))
(defparameter *up* (chan))
(defparameter *ky* (chan))
(defparameter *ms* (chan))
(defun ui-test ()
(let ((move-to (chan))
(typed (chan))
(out *standard-output*))
(labels ((mouse ()
(? *dn*)
(let ((p (? *ms*)))
(format out "moving-mouse to: ~s~%" p)
(force-output)
(! move-to p)
(? *up*)
(mouse)))
(kbd (s)
(let ((c (? *ky*)))
(if (eql c #\newline)
(progn (! typed s)
(kbd ""))
(kbd (concatenate 'string s (string c))))))
(text (p)
(alt ((? move-to coord)
(text coord))
((? typed chars)
(format out "~s::]~s~%" p chars)
(force-output)
(text p)))))
(spawn (kbd ""))
(spawn (text nil))
(spawn (mouse)))))
(defun ui-events (position text)
(! *dn* nil)
(! *ms* position)
(map nil #'(lambda (char) (! *ky* char)) text)
(! *ky* #\newline)
(! *up* nil))
ui-test sets up the event-handlers, and ui-events allows you to drive it:
CSP-TEST> (ui-test)
#<CSP::PROC {B3D7D11}>
CSP-TEST> (ui-events '(3 1) "hello everybody")
moving-mouse to: (3 1)
(3 1)::]"hello everybody"
NIL
CSP-TEST> (ui-events '(5 1) "hi dr. nick")
moving-mouse to: (5 1)
(5 1)::]"hi, dr nick"
NIL
The second example is the sieve of Eratosthenes done using a pipeline of
filters:
;;;sieve of Eratosthenes
(defun sieve-n (n)
(let ((rv-chan (chan))
(out-chan (chan)))
(labels ((processor (p in-chan out-chan)
(let ((n (? in-chan)))
(cond ((eql -1 n)
(! out-chan -1))
(t (when (not (zerop (mod n p)))
(! out-chan n))
(processor p in-chan out-chan)))))
(pipeline (channel)
(let ((prime (? channel))
(new-out (chan)))
(! rv-chan prime)
(when (not (eql -1 prime))
(spawn (processor prime channel new-out))
(pipeline new-out))))
(collect-rv (current)
(let ((n (? rv-chan)))
(if (eql -1 n)
current
(collect-rv (cons n current))))))
(spawn (dotimes (x (- n 2))
(! out-chan (+ x 2)))
(! out-chan -1))
(spawn (pipeline out-chan))
(collect-rv '()))))
It effectively "lays its own track" as the primes that needed to be
filtered get bigger.
CSP-TEST> (sieve-n 50)
(47 43 41 37 31 29 23 19 17 13 11 7 5 3 2)
CSP-TEST>
Anyway, I think it's worth a look.
Matt
--
"You do not really understand something unless you can
explain it to your grandmother." — Albert Einstein.