Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Coroutines in Perl 5

by Ovid (Cardinal)
on Aug 05, 2002 at 23:06 UTC ( #187857=perlmeditation: print w/replies, xml ) Need Help??

So, if I understand coroutines correctly, what about the following idea?

  • Create a function named &yield and export it into the caller's namespace.
  • When the module exporting the &yield is used, it uses B::Deparse to make the calling code easier to parse and then insert unique labels with naked blocks before every &yield.
  • When &yield is called, it uses PadWalker to save the state of the scratchpad and toggles a bit saying that "I've been called", and then returns from the sub using something like rreturn from Want.
  • At the top of every sub, insert a bit of code that goes to the label in front of the last &yield called in that function.
  • The &yield is executed, sees the bit that says "I saved the state last time", so it instead uses PadWalker to restore the state.

Am I missing anything here? This implementation seems a lot simpler (and closer to Perl6 syntax) then the Coro bundle on the CPAN.

As far as I can tell, this would still be a rather limited implementation and might not work with closures. However, it seems so obvious that I know I have to be missing something...

Cheers,
Ovid

Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

Replies are listed 'Best First'.
Re: Coroutines in Perl 5
by Anonymous Monk on Aug 07, 2002 at 02:24 UTC
    The Coro bundle tries to implement continuations. The function that you are looking at is for co-routines.

    You can implement co-routines in terms of continuations. The reverse is not true. But co-routines are enough for a lot of what you want continuations for in practice.

Re: Coroutines in Perl 5
by RMGir (Prior) on Aug 06, 2002 at 19:28 UTC
    Hmmm, you started my mind down a twisty path filled with things like invoking perl with -P and writing strange macros to do yield.

    I hope I can find my way out without actually DOING any of those evil things! :)
    --
    Mike

Re: Coroutines in Perl 5
by rcaputo (Chaplain) on Aug 14, 2002 at 02:35 UTC

    I suggested something similar to perl5-porters in message <199702071400.JAA00295@anshar.shadow.net>. I was writing a MUD in Perl that needed to multitask programs, and I was considering breaking procedural code into small state machines. This is the sample MUD code I included in the message:

      count = 10000000
      while count--
        say "hello, world!  enter some text: "
        getline some_text
        if some_text eq 'quit'
          last
        endif
      endwhile
      say "\ngoodbye, world!\n"

    The idea was to break it into basic blocks-- chunks of code delimited by branches-- and perform implicit yields at each branch. I intended to implement the I/O functions like say() and getline() so they would suspend MUD tasks until the calls had completed.

    My intention was to "compile" the above MUD code by first translating it into Perl and then using eval() to "assemble" it into bytecode. Here's the Perl sub that the previous code would have been translated into:

      sub aaaaa {
        # assumes the existence of a tasking/event kernel
        my $task = shift;
        my $namespace = $task->{"namespace"};
        my $ip = $task->{'instruction pointer'}; # state
    
        # initial entry point
        if ($ip == 0) {
          $namespace->{'count'} = 10000000 ;
          $task->{'instruction pointer'} = 1;
        }
        # top of while loop
        elsif ($ip == 1) {
          if ($namespace->{'count'}--) {
            $task->say(qq(hello, world!  enter some text: ));
            # soft block on 'getline'
            $task->{'blocking'} = 'getline';
            $task->{'instruction pointer'} = 2;
          }
          else {
            $task->{'instruction pointer'} = 3;
          }
        }
        # "return" from getline
        elsif ($ip == 2) {
          $namespace->{'some_text'} = $task->getline();
          if ( $namespace->{'some_text'} eq q(quit) ) {
            $task->{'instruction pointer'} = 3;
          }
          else {
            $task->{'instruction pointer'} = 1;
          }
        }
        # after endwhile
        elsif ($ip == 3) {
          $task->say( qq(\ngoodbye, world!\n) ) ;
          $task->{'instruction pointer'} = -1; # signals end
        }
      }
    

    I thought this was possible in 1997, and I think it may even be practical now that we can manipulate and generate bytecode directly from Perl programs.

    -- Rocco Caputo / poe.perl.org

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://187857]
Approved by kvale
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (5)
As of 2019-10-20 05:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Notices?