use Coro;
use Coro::Cont "yield";
sub foo :Cont { yield 1; yield 3; };
print foo(), "\n";
print foo(), "\n";
Pretty boring. The neat thing is
foo() can have
my variables, and they keep value between calls. It can
yield from in middle of
for loops. Etc, etc. But here's a bit of guts, just for fun. Working on Coro::Cont, I was using -d:Trace (
Devel::Trace), another thing I love.
>> -e:1: use strict; use warnings; use Coro; use lib "."; use Coro::Cont "yield", "csub"; *foo = csub { print "csub: @_\n"; yield 1; print "csub again: @_\n"; yield 3;}; print foo(5),"\n"; print foo(18), "\n";
>> Coro/Cont.pm:130: @ret = @_; # XXX if this works, make it a stack, I guess -- sdw
>> Coro/Cont.pm:131: &Coro::State::transfer(@{pop @$$return});
>> Coro/Cont.pm:131: &Coro::State::transfer(@{pop @$$return});
>> /home/knoppix/lib/perl5/site_perl/5.8.8/i686-linux/Coro/Specific.pm:53: $Coro::current->{_specific}[${$_[0]}];
>> /home/knoppix/lib/perl5/site_perl/5.8.8/i686-linux/Coro/Specific.pm:53: $Coro::current->{_specific}[${$_[0]}];
>> Coro/Cont.pm:116: wantarray ? @ret : $ret[0];
1
>> -e:1: use strict; use warnings; use Coro; use lib "."; use Coro::Cont "yield", "csub"; *foo = csub { print "csub: @_\n"; yield 1; print "csub again: @_\n"; yield 3;}; print foo(5),"\n"; print foo(18), "\n";
>> Coro/Cont.pm:114: push @$$return, [$coro, $prev];
>> /home/knoppix/lib/perl5/site_perl/5.8.8/i686-linux/Coro/Specific.pm:53: $Coro::current->{_specific}[${$_[0]}];
>> /home/knoppix/lib/perl5/site_perl/5.8.8/i686-linux/Coro/Specific.pm:53: $Coro::current->{_specific}[${$_[0]}];
>> Coro/Cont.pm:115: &Coro::State::transfer($prev, $coro);
>> Coro/Cont.pm:132: wantarray ? @_ : $_[0];
>> -e:1: use strict; use warnings; use Coro; use lib "."; use Coro::Cont "yield", "csub"; *foo = csub { print "csub: @_\n"; yield 1; print "csub again: @_\n"
; yield 3;}; print foo(5),"\n"; print foo(18), "\n";
csub again:
>> -e:1: use strict; use warnings; use Coro; use lib "."; use Coro::Cont "yield", "csub"; *foo = csub { print "csub: @_\n"; yield 1; print "csub again: @_\n"
; yield 3;}; print foo(5),"\n"; print foo(18), "\n";
>> Coro/Cont.pm:130: @ret = @_; # XXX if this works, make it a stack, I guess -- sdw
>> Coro/Cont.pm:131: &Coro::State::transfer(@{pop @$$return});
>> Coro/Cont.pm:131: &Coro::State::transfer(@{pop @$$return});
>> /home/knoppix/lib/perl5/site_perl/5.8.8/i686-linux/Coro/Specific.pm:53: $Coro::current->{_specific}[${$_[0]}];
>> /home/knoppix/lib/perl5/site_perl/5.8.8/i686-linux/Coro/Specific.pm:53: $Coro::current->{_specific}[${$_[0]}];
>> Coro/Cont.pm:116: wantarray ? @ret : $ret[0];
@ret holds return values from before to after the call to
Coro::State::transfer.
Coro::State::transfer switches from one execution context to another. It's fun to look at this print out the
-e line of code and have execution teleported from one place in the code to another -- from inside the function to outside of it and back. Not shown,
Coro has a function for creating an execution context object to represent the current execution context, and that's what
$prev is. It keeps these execution contexts on a nice little stack. When you
yield, it pops up a level and does an implicit
return of whatever arguments were passed to
yield. When the function is called again,
transfer is called again to switch execution back into the routine,
foo in our example, and the stack is pushed again, and
foo resumes execution exactly where it left off... right after the
yield.
-scott
I got one of those
awwaiid on 2008-11-16T15:06:18
http://search.cpan.org/dist/Coro-Generator/