From: Charles Oliver Nutter Date: 2011-10-27T13:10:53+09:00 Subject: [ruby-core:40436] Re: [ruby-trunk - Feature #5482][Open] Rubinius as basis for Ruby 2.0 --90e6ba613c7c49490404b03ff58b Content-Type: text/plain; charset=UTF-8 I think it is more important for Ruby to be fast, expressive and easy to use rather than filled with "interesting puzzles" but perhaps I am in a minority there. In any case, I doubt that 99% of developers would care if callcc went away, and it is not supported in several implementations already. - Charlie (mobile) On Oct 26, 2011 10:18 PM, "Yusuke Endoh" wrote: > Hello, Charles > > 2011/10/26 Charles Oliver Nutter : > > On Tue, Oct 25, 2011 at 11:45 PM, Tim Felgentreff 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 > > --90e6ba613c7c49490404b03ff58b Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable

I think it is more important for Ruby to be fast, expressive and easy to= use rather than filled with "interesting puzzles" but perhaps I = am in a minority there. In any case, I doubt that 99% of developers would c= are if callcc went away, and it is not supported in several implementations= already.

-=C2=A0 Charlie (mobile)

On Oct 26, 2011 10:18 PM, "Yusuke Endoh&quo= t; <mame@tsg.ne.jp> wrote:
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 bet= ter
>> optimization _and_ have been shown to be more powerful. shift/rese= t 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.

=C2=A0reset { 2 * shift {|k| 2 } } #=3D> must be 2, not 4


The feature can be implemented by using callcc.

=C2=A0require "continuation"

=C2=A0def shift
=C2=A0 =C2=A0callcc {|c1| $ctn[yield(proc {|v| callcc {|c2| $ctn =3D c2; c= 1[v] } })] }
=C2=A0end

=C2=A0def reset
=C2=A0 =C2=A0callcc {|c| $ctn =3D c; v =3D yield; $ctn[v] }
=C2=A0end


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

=C2=A0p 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:

=C2=A0p reset { [1] + shift {|j| [2] + j[[3]] } + shift {|k| [4] + k[[5]] = } }
#=3D> reset { [1] + [3] + shift {|k| [4] + k[[5]] } }
#=3D> reset { [1] + [3] + [5] }
#=3D> reset { [1] + shift {|j| [2] + j[[3]] } + shift {|k| [4] + [1,3,5]= } }
#=3D> reset { [4,1,3,5] }
#=3D> reset { [1] + shift {|j| [2] + [4,1,3,5] } + shift {|k| [4] + k[5]= } }
#=3D> reset { [2,4,1,3,5] }
#=3D> [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. =C2=A0Bummer.

--
Yusuke Endoh <mame@tsg.ne.jp>
--90e6ba613c7c49490404b03ff58b--