[racket] Engineering Tradeoffs of ANF transforms and the Stateless Server
Nice!
(as you can tell, I didn't see that when I wrote my first reply to you....)
Robby
On Sat, Dec 31, 2011 at 9:22 PM, Galler <lzgaller at optonline.net> wrote:
> Section five
>
> "Although the continuation-marks procedure has been a part of PLT Scheme for
> years, we have not yet found a use for it"
>
> I think we've found a use for it.
>
>
>
>>>>
>
> Robby,
>
> Section 5 of your paper notes the function (continuation-marks cont)
>
> provides the continuation marks of an arbitrary continuation at time of
> reification.
>
> Illustrative code snippet below
>
> That certainly takes care of a lot of the problems associated with
> implementing a solution to chain exit and entry actions.
>
> Thanks very much for sharing the paper.
>
> I had no idea!
>
>
>
> #lang web-server
>
> (define *s2-k* #f)
>
>
> (define (nextproc)
> (list ;have to have an intermediate function, or it will replace prior mark
> (tail-calling
> (with-continuation-mark 'state '(S2 beforeproc afterproc) ((λ ()
>
> (call/cc (λ (k) (set! *s2-k* k)) (default-continuation-prompt-tag))
> (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))
> (printf "in
> S3 s2's continuation marks are ~A\n" (continuation-mark-set->list
>
> (continuation-marks *s2-k*) 'state)))))
>
> ))
>
>
>
> (with-continuation-mark 'state '(S1 beforeproc afterproc) (nextproc))
>
>
>
>
>
> On Sat, Dec 31, 2011 at 9:36 PM, Robby Findler wrote:
>
>> 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