[racket] Engineering Tradeoffs of ANF transforms and the Stateless Server

From: Galler (lzgaller at optonline.net)
Date: Sat Dec 31 22:22:23 EST 2011

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



Posted on the users mailing list.