[racket] Engineering Tradeoffs of ANF transforms and the Stateless Server
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 <lzgaller at 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 <lzgaller at 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