FWIW, this is essentially re-implementing dynamic-wind (but it is not too difficult if you are familiar with continuations). One thing to watch out for: the lists of continuation marks will, in some cases, share a tail. In that case you'll want to avoid exiting and re-entering the same things. Also worth noting here, I think, you may need to use some kind of unique values in the marks to be able to tell if the shared tails _really_ are shared or if they simply have the same structure.
You might find this paper useful to sort out some of the subtleties: http://www.cs.utah.edu/plt/delim-cont/ hth, Robby On Sat, Dec 31, 2011 at 8:18 PM, Galler <lzgal...@optonline.net> wrote: > Robby, > > Thanks > > Not at all opaque. I was experimenting with that earlier this afternoon, as > below. > > Actuallly, the way you phrased it helps clarify something I was struggle > with. > > A very useful and valuable suggestion. I think that may very well be plan > B. > > R./ > Zack > > > (define (nextproc) > ;need an intermediate function, or it will replace prior mark (tail-calling > (list > (with-continuation-mark 'state '(S2 beforeproc afterproc) ((λ () > (printf "in > S2 ~A\n" (continuation-mark-set->list > > (current-continuation-marks) 'state))))) > (with-continuation-mark 'state '(S3 beforeproc afterproc) ((λ () > (printf "in > S3 ~A\n" (continuation-mark-set->list > > (current-continuation-marks) 'state))))))) > > > (with-continuation-mark 'state '(S1 beforeproc afterproc) (nextproc)) > > > > > On Sat, Dec 31, 2011 at 9:03 PM, Robby Findler wrote: > >> I'm not sure if the web-server supports continuation marks or not, but >> if it does, you could use continuation marks to note what the exit and >> entry operations are, and then when you would do a continuation jump, >> first grab the continuation marks from one side, do the jump, grab the >> continuation marks from the other side, and then explicitly do the >> actions that the marks have recorded should be done. (Let me know if >> that is too opaque ...) >> >> Robby >> >> On Sat, Dec 31, 2011 at 7:56 PM, Galler <lzgal...@optonline.net> wrote: >>> >>> Sorry, should have included a brief example. >>> >>> Here's an example of what I've implemented, which is just Harel's >>> hierarchical state machines >>> >>> You can create a Hierarchical State Machine by defining individual nodes >>> in >>> a flat file, as below. >>> >>> each node has 6 keyword parameters , state, parent, entry, init, exit, >>> and a >>> handler. >>> >>> The machine is very much like a web-server. It receives a signal (akin to >>> a >>> request), processes the signal which may cause a change internal state, >>> and >>> returns a continuation to be invoked when the next signal is presented. >>> >>> The new signal is the argument provided to this continuation at >>> invocation. >>> >>> In the stateful server, the HSM continuation is closed over by the PLT >>> Server's external continuation (reified by send/suspend) >>> >>> In the stateless version, I would replace the HSM continuation with the >>> PLT >>> server's continuation (reified by send/suspend). >>> >>> I can't do that right now because the continuation is in the scope of the >>> dynamic-wind function, which is an unsafe place to capture continuations >>> for >>> #lang web-server >>> >>> The dynamic wind is used as follows: >>> >>> At present, the nodes are brought into the correct tree-like dynamic >>> extent >>> by a recursive function which invokes dynamic-wind. >>> >>> Note that the handler code supports jumping to another state (trans 'S2 >>> 'S3). >>> >>> Trans invokes a continuation reified earlier associated with state S3. In >>> this case, the invocation of the continuation calls the exit actions of >>> state S2 and the entry actions of S3. >>> >>> That's where the dynamic-wind comes in. Its necessary for transitions >>> between states and but used for anything else. >>> >>> That's why I think an overridden call/cc-dynamic-wind and dynamic wind >>> would >>> be sufficient. >>> >>> >>> >>> (defnode >>> #:state 'S2 >>> #:parent 'Top >>> #:entry (λ () (I-TLL:entry-start-TLL)) >>> #:init (lambda () (trans 'S2 'S3)) >>> #:exit (λ () (I-TLL:exit-secure-TLL)) >>> #:handler (λ (signal) >>> (cond >>> [(signal-eq? signal "main") (trans 'S2 'S3)] >>> [(signal-eq? signal "info") (trans 'S2 'S4)] >>> [(signal-eq? signal "about") (trans 'S2 'S5)] >>> [(signal-eq? signal "item") (trans 'S2 'S6)] >>> [(signal-eq? signal "field") (trans 'S2 'S7)] >>> [(signal-eq? signal "dispatch") (trans 'S2 'S8-3)] >>> [(signal-eq? signal "burden") (trans 'S2 'S8-2)] >>> [(signal-eq? signal "planning") (trans 'S2 'S8-1)] >>> [(signal-eq? signal "failentry") (trans 'S2 'S3)] >>> [else #f]))) >>> >>> >>> ____________________ >>> Racket Users list: >>> http://lists.racket-lang.org/users ____________________ Racket Users list: http://lists.racket-lang.org/users