[plt-scheme] Fun with Unicode and delimited continuations

From: Jon Rafkind (rafkind at cs.utah.edu)
Date: Thu Jun 3 13:53:56 EDT 2010

On 06/03/2010 11:40 AM, John Clements wrote:
> On Jun 3, 2010, at 10:19 AM, Jon Rafkind wrote:
>
>    
>> On 06/03/2010 11:07 AM, Eli Barzilay wrote:
>>      
>>> On Jun  3, Matthias Felleisen wrote:
>>>
>>>        
>>>> On Jun 3, 2010, at 12:31 PM, John Clements wrote:
>>>>
>>>>
>>>>          
>>>>>> Sorry, maybe this wasn't clear: I mean e.g. the python 'yield',
>>>>>> which allows a function to return multiple values in a serialized
>>>>>> form.
>>>>>>
>>>>>>              
>>>> If you can write a yield + create a two-element structure in Python
>>>> that way, you can mimic delimited continuations.
>>>>
>>>>
>>>>
>>>>          
>>>>> The only problem with this mechanism is that the yield boundary is
>>>>> fixed on entry to the function call.
>>>>>
>>>>>            
>>>> That's minor. Reset is next to the function entry point too.
>>>>
>>>> Go for it. Show us that Python has delimited continuations.
>>>>
>>>>          
>>> Here's some quick code:
>>>
>>>    #lang scheme
>>>    (require scheme/generator)
>>>    (define (foo x y) (yield x) (yield (+ x y)))
>>>    (define (bar a b c)
>>>      (generator             ; v5 will require () after `generator'
>>>        (for* ([x (in-generator (foo a b))]
>>>               [y (in-generator (foo x c))])
>>>          (yield y))))
>>>    (define g (bar 100 10 1))
>>>    (g) (g) (g) (g)
>>>
>>> where `foo' is the moral equivalent of plus/minus.  Given that this
>>> uses exactly the feature that scheme/generator has that python doesn't
>>> (it uses a dynamic `yield' so it can be used in "helper" functions),
>>> it would be interesting to see if there's a way to do that in python.
>>>
>>> (I think that Jon looked for an example that shows the difference.)
>>>
>>>
>>>        
>> This python program behaves the same, although it would break if one of the `yield's in (foo) were moved to a helper function, like
>>
>> (define (foo1 x) (yield x))
>> (define (foo x y) (yield x) (foo1 (+ x y)))
>>
>> # -- python --
>> def foo(x, y):
>>     yield x
>>     yield x + y
>>
>> def bar(a, b, c):
>>     for x in foo(a, b):
>>         for y in foo(x, c):
>>             yield y
>>
>> for n in bar(100, 10, 1):
>>     print n
>> # -- end --
>>      
>
> Right... the problem with this is that the body of bar gets horribly mangled, and the calls to foo have to be lifted out.  This is basically the partial CPSing that would be required to implement this without generators.
>
> I'm wondering, though: if you "capture a continuation" by using a yield in Python, and make a copy of the resulting generator, can you enter the two resulting "continuations" separately, or does the copied object contain a reference to state that gets messed up?
>    

Looks like you can't copy python generators (at least using the `copy' 
module). I get this error when I use either copy.copy or copy.deepcopy:

TypeError: object.__new__(generator) is not safe, use generator.__new__()

Anyway, python gives you delimited continuations but the reset is 
implicitly the start of the function where the yield is used.


Posted on the users mailing list.