Hello, Charles

2011/10/26 Charles Oliver Nutter <headius / headius.com>:
> On Tue, Oct 25, 2011 at 11:45 PM, Tim Felgentreff <tim / nada1.de> wrote:
>> Can we have partial continuations instead? They allow for much better
>> optimization _and_ have been shown to be more powerful. shift/reset style
>> continuations, maybe?
>
> Fun hack of the night: https://gist.github.com/1315794
>
> I'm sure it's not perfect, but it runs simple things correctly.


That is not a partial continuation.
A shift should first evaluate the given block, and then
*jump to the corresponding reset* with the result.
The execution must not return to reset's block.

  reset { 2 * shift {|k| 2 } } #=> must be 2, not 4


The feature can be implemented by using callcc.

  require "continuation"

  def shift
    callcc {|c1| $ctn[yield(proc {|v| callcc {|c2| $ctn = c2; c1[v] } })] }
  end

  def reset
    callcc {|c| $ctn = c; v = yield; $ctn[v] }
  end


You may think you can implement the feature in pure Ruby
by an exception or catch/throw.  But I guess it is
difficult because it requires reentrant to a shift's
block.  For example,

  p reset { [1] + shift {|j| [2] + j[[3]] } + shift {|k| [4] + k[[5]] } }

prints [2, 4, 1, 3, 5].

It is difficult for me to explain how it does in English :-)
I just show a pseudo reduction diagram:

  p reset { [1] + shift {|j| [2] + j[[3]] } + shift {|k| [4] + k[[5]] } }
#=> reset { [1] + [3] + shift {|k| [4] + k[[5]] } }
#=> reset { [1] + [3] + [5] }
#=> reset { [1] + shift {|j| [2] + j[[3]] } + shift {|k| [4] + [1,3,5] } }
#=> reset { [4,1,3,5] }
#=> reset { [1] + shift {|j| [2] + [4,1,3,5] } + shift {|k| [4] + k[5] } }
#=> reset { [2,4,1,3,5] }
#=> [2, 4, 1, 3, 5]


Check out Olivier's original paper if you are interested.

- Olivier Danvy and Andre Filinski (1990). "Abstracting Control".


If callcc would be removed in 2.0, we should lose a right
to play with such an interesting puzzle.  Bummer.

-- 
Yusuke Endoh <mame / tsg.ne.jp>