On Wed, Jun 24, 2009 at 05:01:17PM -0400 or thereabouts, Jonathon McKitrick wrote:
> What is the purpose of NAME in the FSM macro?
Excellent question.
> (defmacro fsm (name &rest body)
> (unless (symbolp name) (error "fsm needs symbol for name"))
> `(let (,name)
> (declare (ignorable ,name))
> (setq ,name (lambda () ,@body))))
>
>
> Is that just so BODY can return its own name as its last form?
Yes, precisely. An anaphor like self wouldn't work here because nested
fsm forms would then be ambiguous:
(fsm
(fsm
self)) ; wrong
^^^^ Would self refer to the inner or the outer one?
> Because when the result of FSM is returned, it is inserted into a hash
> table, but it doesn't seem that NAME matters after that...
NAME is intended to be a lexical binding so that symbol is completely
removed at compile time. It's only there to sort out the above mentioned
ambiguity and provide the programmer a way to choose exactly which state
the state machine should switch to next.
Yes, whatever fsm returns is inserted into a hash table. Usually this
is another closure created with fsm but sometimes it is a symbol:
(fsm blah
... do some stuff ...
'the-blah-connection-should-now-be-closed)
A symbol is only returned when we have closed (or lingered) a connection
and thus don't expect to get any more events on it. If we do get an
event on such a connection, Antiweb will see that it's a symbol in the
hash table and not a closure and will then report the offending symbol
in the syslog so it's easy to debug which fsm form has the bug.
Returning a symbol is kind of a short-cut for the following:
(fsm blah
... do some stuff ...
(lambda ()
(fatal "Should never get here but in case it does, we were inside the blah fsm")))
These connections remain in the hash table and the connection list
until they are reaped by the connection zombie reaper.
Hope this helps,
Doug
PS. I'm CCing this to the Antiweb list because it's a great question.