Hello - I would appreciate some advice on how to implement something equivalent to sub-classing.
The context for this is a finite state machine (FSM), by which I mean a thread that waits on a queue of events, then deals with each event (one at a time) according to the state it is in, possibly changing state in the process. In Java, an (abstract) super class might be defined for all FSMs, which contains common fields such as the current state, timer ID, event queue, etc, together with methods for getting and setting the state, starting and stopping timers, handling timeouts (this inserts a timeout event into the event queue), putting an event into the queue and waiting on the next event in the queue. The method to insert an event is generally public so that other objects may insert events. Then, a particular FSM is written as a sub-class; this comprises code to execute before the first event is waited for, a loop which waits for then processes each event, then code that is executed when the FSM is exited for the last time. The code that implements all the above naturally makes use of the super-class methods and fields, since they are within the scope of the sub-class. It is easy enough to implement all the above as closure of the form (defn fsm [] "Start a thread that is a finite state machine. Return [putEventF stopF] where putEventF[ev] is a function that adds an event to the event queue, and stopF[] is a function that stops the state machine. Events are vectors of the form [kind & data]." (let [eventQ (java.util.concurrent.LinkedBlockingQueue.) putEventF (fn [ev] (.put eventQ ev)) stopF (fn [] (putEventF [:stop])) state (atom nil) going (atom true) timerID (atom nil) timerExpired (fn [id data] (when (and @timerID (= id timerID)) (.put eventQ [:timeout data]))) stopTimer (fn [] (when @timerID (extStopTimer @timerID) (reset! timerID nil))) startTimer (fn [period data] (stopTimer) (reset! timerID (extStartTimer period timerExpired data))) nextState #(reset! state %)] (inThread (do (nextState :init) ; Starting stuff ... (print "started")) (while @going (let [[kind & data :as ev] (.get eventQ)] (cond = @state :init (do ; Initialization stuff ... ) :state1 (do ; state 1 stuff ... ) :state2 (do ; state 2 stuff ... ) ; etc... :stop (do ; Stopping stuff ... (reset! going false)) (error "bad state")))) (do ; Exit stuff ... (print "terminated"))) [putEventF stopF])) where extFunction... are externally defined functions (implementing timers etc) and inThread is a macro that executes a form in a newly created thread. Within the body of the FSM, the code can of course directly refer to all the things defined in the let by name. The problem is that I have numerous FSMs and it's really tedious to repeat all the stuff in the initial let of the closure. One solution is to define a *context* that contains the values defined in the closure (as a map with keys instead of the explicit names shown above), created by a context factory function. Then the code has to refer to all the things via a lookup in the context map - quite ugly and also tedious. Another option is that the context factory creates a closure, then returns a vector of all the functions defined in the let binding, which can then be used directly by the FSM code - that's even more ugly and error prone. So - the question is - what about an anaphoric macro that creates the closure, so that the FSM code can still refer to all that stuff by name? If this is the way to go, please an example of the syntax (say the timerExpired function). The macro syntax really is confusing to me :( Or, I imagine a macro called myFsmMacro that takes a map as parameter and has the same effect as the fsm function above, something like this: (def myFsmDefinition { :preamble (do (nextState :init) (print "started")) :states {:init (do (initData 1 2 3) (putEvent :dummy) (nextState :state1)) :state1 (do (startTimer 10) (nextState :state2)) :state2 (condp = kind :timeout ;.... ) .... all the other states :stop (do (reset! going false)) } :badState (error "bad state") :postAmble (do ; Exit stuff ... (print "terminated")) }) (myFsmMacro myFsmDefinition) --> [putEventF stopF] Is this feasible? Not as it stands - the map would be full of undefined things. Or, is this an appropriate application of mutimethods (one method per state)? Or, define myFsmDefinition as text, parse it, create form and then eval it? I don't fully understand Monads, could this be an application of the state monad? Or does the state have to be explicitly passed around just like the context I mentioned above? And would it make those local names visible to the FSM code? Or some new kind of monad? Any comments would be appreciated. Regards, Tim -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en