Continuation usage

Discussion in 'Ruby' started by Patrick Roemer, Apr 11, 2004.

  1. Once again I've been trying to get a grip on continuations, however, I'm
    quite unsure whether I've really got it this time. Could anybody please
    take a look at the example 'server' below. It seems to work when called
    from irb, but I'm unclear on how to test such a beast programmatically,
    so I suspect I somehow must have got it wrong again.

    TIA,
    Patrick

    class ContServer
    def initialize()
    @blocks={} # named services
    @mains={} # top-level continuations by session id
    @conts={} # service continuations by session id
    end

    def add(name,&block)
    @blocks[name]=block
    end

    def service(id,name='',inp='')
    callcc do |cc|
    @mains[id]=cc # remember top-level continuation
    if(@conts.key?(id)) # already in session?
    @conts[id].call(inp) # return to service continuation
    else
    ret=@blocks[name].call(id,self) # enter new session
    @conts.delete(id) # finish session
    ret
    end
    end
    end

    def io(id,out)
    callcc do |cc|
    @conts[id]=cc # remember service continuation
    @mains[id].call(out) # return to top-level continuation
    end
    end

    def ContServer::init
    cs=ContServer.new
    cs.add('guess') do |id,server|
    target=rand(100)
    inp=server.io(id,"Please enter a number between 1 and 100.").to_i
    round=1
    while(inp!=target)
    inp=server.io(id,(inp < target ? "Higher" : "Lower")).to_i
    round += 1
    end
    "You found it in #{round} rounds."
    end
    cs
    end
    end
     
    Patrick Roemer, Apr 11, 2004
    #1
    1. Advertising

  2. Patrick Roemer

    Chad Fowler Guest

    On 11/4/2004, at 6:44 AM, Patrick Roemer wrote:

    > Once again I've been trying to get a grip on continuations, however,
    > I'm
    > quite unsure whether I've really got it this time. Could anybody please
    > take a look at the example 'server' below. It seems to work when called
    > from irb, but I'm unclear on how to test such a beast programmatically,
    > so I suspect I somehow must have got it wrong again.
    >
    > TIA,
    > Patrick
    >

    --snip--code

    How are you calling it from IRB? It didn't work for me, and before I
    spent too much time trying to figure out why, I thought I'd ask this
    first.

    Chad
     
    Chad Fowler, Apr 11, 2004
    #2
    1. Advertising

  3. Chad Fowler wrote:

    > How are you calling it from IRB? It didn't work for me, and before I
    > spent too much time trying to figure out why, I thought I'd ask this
    > first.


    Thanks for your reply. I have to admit that 'calling from irb' is not a
    very detailed description. ;) I meant something like this:

    irb(main):001:0> require 'conttest.rb'
    => true
    irb(main):002:0> cs=ContServer.init
    => #<ContServer:0x2812560 @conts={},
    @mains={}, @blocks={"guess"=>#<Proc:0x02812548@./conttest.rb:34>}>
    irb(main):003:0> cs.service(1,'guess',50) # (last arg ignored)
    => "Please enter a number between 1 and 100."
    irb(main):004:0> cs.service(1,'guess',50) # (middle arg ignored)
    => "Lower"
    irb(main):005:0> cs.service(1,'guess',25) # (middle arg ignored)
    => "You found it in 2 rounds."
    irb(main):006:0> cs.service(1,'guess',25) # (last arg ignored)
    => "Please enter a number between 1 and 100."
    irb(main):007:0> cs.service(1,'guess',50) # (middle arg ignored)
    => "Higher"

    ....and so on. This also seems to work with multiple 'services' and
    multiple 'users' (i.e. IDs) with interleaved access.

    Please try to ignore the crappy arg handling (and also the off-by-one
    error for the random expectation). I'm just trying to figure out how a
    continuation-based web server is supposed to work. For me this was the
    'simplest thing that could possibly emulate this'. Perhaps I am totally
    off the track, but if so, I'd really like to know why.

    Regards,
    Patrick
     
    Patrick Roemer, Apr 12, 2004
    #3
  4. Hi,

    On Sun, 11 Apr 2004 12:41:50 +0200, Patrick Roemer wrote:

    > Once again I've been trying to get a grip on continuations, however, I'm
    > quite unsure whether I've really got it this time. Could anybody please
    > take a look at the example 'server' below. It seems to work when called
    > from irb, but I'm unclear on how to test such a beast programmatically,
    > so I suspect I somehow must have got it wrong again.
    >


    This looks very solid to me. Maybe you could make every
    Service a subclass of ContSession, and every session an
    instance of that session. It would look something like this:

    class ContSession
    def start(*args)
    callcc do |cc|
    @main = cc
    session(*args)
    end
    end

    def service(arg)
    callcc do |cc|
    @main = cc
    @cont.call(arg)
    end
    end

    def io(out)
    callcc do |cc|
    @cont = cc
    @main.call(out)
    end
    end
    private :io
    end

    class Guess < ContSession
    def session
    target = rand(100)
    inp = io("Please enter a number between 1 and 100.").to_i
    round = 1
    while(inp != target)
    inp = io(inp < target ? "Higher" : "Lower").to_i
    round += 1
    end
    "You found it in #{round} rounds."
    end
    private :session
    end

    irb(main):002:0> g = Guess.new
    #<Guess:0x402a7484>
    irb(main):003:0> g.start
    "Please enter a number between 1 and 100."
    irb(main):004:0> g.service(50)
    "Lower"
    irb(main):005:0> g.service(25)
    "Higher"
    irb(main):006:0> g.service(37)
    "Lower"
    irb(main):007:0> g.service(31)
    "Higher"
    irb(main):008:0> g.service(34)
    "You found it in 5 rounds."
     
    Kristof Bastiaensen, Apr 12, 2004
    #4
  5. Hi,

    On Sun, 11 Apr 2004 12:41:50 +0200, Patrick Roemer wrote:

    > Once again I've been trying to get a grip on continuations, however, I'm
    > quite unsure whether I've really got it this time. Could anybody please
    > take a look at the example 'server' below. It seems to work when called
    > from irb, but I'm unclear on how to test such a beast programmatically,
    > so I suspect I somehow must have got it wrong again.
    >


    It looks very solid to me. Maybe you could make every Service a
    subclass of ContSession, and every session an instance of that Session.
    It would look something like this:

    class ContSession
    def start(*args)
    callcc do |cc|
    @main = cc
    session(*args)
    end
    end

    def service(arg)
    callcc do |cc|
    @main = cc
    @cont.call(arg)
    end
    end

    def io(out)
    callcc do |cc|
    @cont = cc
    @main.call(out)
    end
    end
    private :io
    end

    class Guess < ContSession
    def session
    target = rand(100)
    inp = io("Please enter a number between 1 and 100.").to_i
    round = 1
    while(inp != target)
    inp = io(inp < target ? "Higher" : "Lower").to_i
    round += 1
    end
    "You found it in #{round} rounds."
    end
    private :session
    end

    irb(main):002:0> g = Guess.new
    #<Guess:0x402a7484>
    irb(main):003:0> g.start
    "Please enter a number between 1 and 100."
    irb(main):004:0> g.service(50)
    "Higher"
    irb(main):005:0> g.service(75)
    "Higher"
    irb(main):006:0> g.service(81)
    "Higher"
    irb(main):007:0> g.service(90)
    "Higher"
    irb(main):008:0> g.service(95)
    "Lower"
    irb(main):009:0> g.service(93)
    "Lower"
    irb(main):010:0> g.service(91)
    "You found it in 7 rounds."
    irb(main):011:0>
     
    Kristof Bastiaensen, Apr 12, 2004
    #5
  6. -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA1

    Patrick Roemer wrote:

    | Once again I've been trying to get a grip on continuations, however, I'm

    Your code looks solid and as though you have been trough with the
    concept. Might I suggest the source code of Borges for further reading
    on this subject ? ;)

    (I guess you know Seaside and/or other Continuation based web
    programming frameworks, there seems to be a bit of talk about that lately).

    kaspar - code philosopher

    - -- stolen off the net --
    So much for taking the world by storm. I guess I'll have to take it by
    siege.
    -- Jay J. P. Scott
    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.2.4 (MingW32)
    Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

    iD8DBQFAenD4Fifl4CA0ImQRAm8pAJsH4XLFKxKAkZ5IHNZk41XthXP79wCfZAjc
    IqU0lwab1IAA4cwdsFtINC8=
    =cgpK
    -----END PGP SIGNATURE-----
     
    Kaspar Schiess, Apr 12, 2004
    #6
  7. Kristof Bastiaensen wrote:

    > It looks very solid to me.


    In the meantime I've found out that the problem was not in the code I
    posted, but in my test. :/

    Your version looks really nice. I think it could fit nicely with the
    other continuation examples in the Ruby FAQ. Thanks.

    Regards,
    Patrick
     
    Patrick Roemer, Apr 12, 2004
    #7
  8. Kaspar Schiess wrote:

    > Your code looks solid and as though you have been trough with the
    > concept. Might I suggest the source code of Borges for further reading
    > on this subject ? ;)


    Good idea, I hadn't discovered Borges yet.

    > (I guess you know Seaside and/or other Continuation based web
    > programming frameworks, there seems to be a bit of talk about that lately).


    I've found continuations in Cocoon's flow script (i.e. in Cocoon's
    Javascript/Rhino extension), but before using it, I wanted to get a grip
    on the basic concept and I felt more comfortable experimenting with it
    in Ruby rather than Javascript or Scheme. Now that I seem to have got
    it, I'll have a look at Borges to see it in action. Thanks for the hint.

    Regards,
    Patrick
     
    Patrick Roemer, Apr 12, 2004
    #8
  9. Patrick Roemer

    Chad Fowler Guest

    On 12/4/2004, at 7:39 AM, Patrick Roemer wrote:

    >>

    >
    > I've found continuations in Cocoon's flow script (i.e. in Cocoon's
    > Javascript/Rhino extension), but before using it, I wanted to get a
    > grip
    > on the basic concept and I felt more comfortable experimenting with it
    > in Ruby rather than Javascript or Scheme. Now that I seem to have got
    > it, I'll have a look at Borges to see it in action. Thanks for the
    > hint.
    >


    I've also written a tiny bit of code to attempt to educate myself and
    others on how Seaside-like frameworks work. I plan to eventually
    implement all of the "tricks" that Seaside employs in as little code as
    possible (with the goal being clarity--not brevity). Right now I just
    have the first trick implemented. The code is really stupid, but
    that's beside the point. :)

    http://chadfowler.com/lazyseaside/pm_seaside.html

    Ignore the "seasidehints.out" and "wrap_methods" stuff. That's
    unrelated and part of another idea I was exploring
    (http://chadfowler.com/index.cgi/Computing/Programming/Ruby/
    TypeWatching.rdoc,v).


    Chad
     
    Chad Fowler, Apr 12, 2004
    #9
  10. -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA1

    | I've found continuations in Cocoon's flow script (i.e. in Cocoon's
    | Javascript/Rhino extension), but before using it, I wanted to get a grip
    | on the basic concept and I felt more comfortable experimenting with it
    | in Ruby rather than Javascript or Scheme. Now that I seem to have got
    | it, I'll have a look at Borges to see it in action. Thanks for the hint.

    Have a look at Borges then, it does what you want and ten times more: It
    rocks ! (Having come the same way from Cocoon... )


    kaspar - code philosopher

    - -- stolen off the net --
    "It takes real courage to be a Macintosh user; it takes real conviction;
    ~ not unlike being a Christian in the days of the Romans."
    ~ - Guy Kawasaki, Chief Evangelist for Apple Computer - from "Hotseat"
    ~ interview with John McChesney (3/28/97)
    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.2.4 (MingW32)
    Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

    iD8DBQFAeoLCFifl4CA0ImQRAiBDAKCLe4eZRf+/8DRCbN+9U25Z8TU6jgCgtjcK
    gJypeQXuVBj1rhYW0sbKxzI=
    =BR3H
    -----END PGP SIGNATURE-----
     
    Kaspar Schiess, Apr 12, 2004
    #10
  11. On Mon, 12 Apr 2004 13:36:13 +0200, Patrick Roemer wrote:

    > Your version looks really nice. I think it could fit nicely with the
    > other continuation examples in the Ruby FAQ. Thanks.
    >


    Thanks!
    Maybe you are interested in the following code (if it
    doesn't exist already). In implements a kind of goto:

    class Mark
    def initialize
    @cc = callcc { |cc| cc }
    end
    def goto #should be called teleport
    @cc.call(@cc)
    end
    end

    #-- (the example is quite stupid, but just to show the concept)

    irb(main):006:0> begin
    irb(main):007:1* a = Mark.new
    irb(main):008:1> a.goto if gets.chomp != "stop"
    irb(main):009:1> end
    Hi, there
    Everything ok!
    stop
    nil
    irb(main):010:0>

    #----
     
    Kristof Bastiaensen, Apr 12, 2004
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. KathyB
    Replies:
    2
    Views:
    1,926
    Mario Vargas
    Jul 17, 2003
  2. DC

    Continuation question....

    DC, May 24, 2005, in forum: ASP .Net
    Replies:
    2
    Views:
    458
  3. aarthy kumar
    Replies:
    3
    Views:
    389
    =?Utf-8?B?Q293Ym95IChHcmVnb3J5IEEuIEJlYW1lcikgLSBN
    Oct 12, 2005
  4. TheDustbustr

    stackless python: continuation module?

    TheDustbustr, Jul 25, 2003, in forum: Python
    Replies:
    2
    Views:
    463
    Christian Tismer
    Aug 6, 2003
  5. Sandra-24
    Replies:
    5
    Views:
    416
    Leif K-Brooks
    Apr 9, 2006
Loading...

Share This Page