--J2pR2RtFp0tAjF3C
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

Ben Giddings (ben / thingmagic.com) wrote:

> On Wed August 6 2003 6:45 pm, Dan Sugalski wrote:
> > >1) Why do they have the strange syntax they have
> > 
> > They don't--there's no inherent strange syntax to them. The syntax 
> > comes from the language implementing the continuation semantics.
> 
> Like Hal said, I meant why do they have the strange syntax they do "in Ruby".  
> There just doesn't seem to be a good reason for a block.  It also seems 
> strange to have a class with no constructor that can only be created by a 
> Kernel method.

The advantage to the block is that it allows you to do some stuff
with the continuation (like saving this potential chain of execution)
without continuaing.  Not having the block makes things much more
difficult.

Take a look at the guts of Borges, particuarly Session.rb.

http://segment7.net/ruby-code/borges/borges.html


If you read below, you'll see the continuation captures what you're
doing in respond, and saves it, and doesn't return until you invoke
that continuation.  The block allows you to do some stuff, *then*
invoke, but only if you really want to in the convenient ruby
metaphor.

You may have to read more of the code to really understand what's
going on here, I only understand enough of it to have an intuitive
feel for the deep magic that's going on inside.  I couldn't rewrite it
from scratch.

class Session

  # ...

  def handle_request_intern(request, response)
    @response = response
    @current_key = request.action_key
    callcc do |cc|
      @short_jmp = cc # *** note this
      if cont = @continuations[@current_key]
        # if there is a continuation for current_key, invoke
        cont.call(request)
      else
        # handle unknown requests
        unknown_request(request)
      end
    end
    @last_key = @current_key
  end

  # ...

  def respond
    callcc do |cc|
      @response.action_key = @continuations.store(cc)
      yield(@response)
      @short_jmp.call # *** is used here
    end
  end

end

And this code gets used in Renderer.rb:

  def render_response
    @callbacks = CallbackStore.new
    request = respond do |res|
      @response = @stream = res
      yield(self)
    end
    @callbacks.process_callbacks(request)
  end

  def text_input(value, attrs={}, &update)
    attrs["value"] = value
    # This only gets invoked if this action is chosen.
    attrs["name"] = @callbacks.register_callback(update)
    input("text", attrs)
  end

> Is there some reason that Continuation.new couldn't work?

I don't know if this is 100% correct:

class Continuation
  def self.new
    if block_given? then
      callcc { |c| yield(c) }
    else
      callcc { |c| return c }
    end
  end
end


-- 
Eric Hodel - drbrain / segment7.net - http://segment7.net
All messages signed with fingerprint:
FEC2 57F1 D465 EB15 5D6E  7C11 332A 551C 796C 9F04


--J2pR2RtFp0tAjF3C
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.2 (FreeBSD)

iD8DBQE/MZJ4MypVHHlsnwQRAqDqAKCUF+D2Vtm8aZ5xpsAxq4/Xfyt9HwCfdNgY
KmDMkK1c+XXDc/nfNCgEJw8MR
-----END PGP SIGNATURE-----

--J2pR2RtFp0tAjF3C--