coroutine0
view release on metacpan or search on metacpan
coroutine0.pm
Makefile.PL
MANIFEST
README
t/1.t
Makefile.PL view on Meta::CPAN
use 5.000;
use ExtUtils::MakeMaker;
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
# the contents of the Makefile that is written.
WriteMakefile(
'NAME' => 'coroutine0',
'VERSION_FROM' => 'coroutine0.pm', # finds $VERSION
'PREREQ_PM' => {}, # e.g., Module::Name => 1.1
($] >= 5.005 ? ## Add these new keywords supported since 5.005
(ABSTRACT_FROM => 'coroutine0.pm', # retrieve abstract from module
AUTHOR => 'david <david@localdomain>') : ()),
);
coroutine0 version 0.02
=======================
For the purposes of this module, a coroutine is considered to be a subroutine that
maintains its state and execution position between calls to it. To return from
a coroutine but start up where you left off, use C<YIELD> instead of C<return> to
send a result back to the caller.
The coroutine declaration syntax leaves much to be desired. The 0 is suffixed to
the module name so the coroutine module, when it finally appears, will not have
to support this clunky code-in-string-paired-with-BODY-keyword syntax.
INSTALLATION
To install this module type the following:
perl Makefile.PL
make
make test
coroutine0.pm view on Meta::CPAN
package coroutine0;
use 5.000;
use strict;
use vars qw($VERSION @ISA %bodystrings);
@ISA = qw();
$VERSION = '0.02';
#my %bodystrings;
my $labname = 'corolab';
use Carp;
sub rewrite($){
my $l = $labname++;
<<EOF;
\$LABEL='$l';
return $_[0];
$l:
EOF
coroutine0.pm view on Meta::CPAN
sub DESTROY{
delete $bodystrings{$_[0]};
};
1;
__END__
=head1 NAME
coroutine0 - a working but ugly coroutine generator
=head1 SYNOPSIS
use coroutine0;
sub one_to_N($);
*one_to_N = new coroutine0
VARS => [qw/$i/],
BODY => <<'END_OF_BODY', # single-quotes for q{} not qq{}
$i = 1;
while ($i < 11){
YIELD $i++;
};
END_OF_BODY
PROTO => '($)', # gets pasted in whole: parens are required
TIDY => 0;
# these have their own sequences:
*another_one_to_ten = copy {\&one_to_N} ; #indirect
*yet_another_one_to_ten = (\&one_to_N)->copy(); #direct
# this one shares one_to_N's sequence:
*same_sequence = \&one_to_N;
=head1 ABSTRACT
coroutines using closures to provide lexical persistence
=head1 DESCRIPTION
C<new> takes a list and returns a blessed coderef. The defined
argument keys include C<VARS> and C<BODY>. Lexicals meant
to persist between calls to a routine are listed in C<VARS>.
The C<new> function works by rewriting each instance
of /\bYIELD\b.*;/ within the body to a labeled exit/entry point
and wrapping the rewritten body in an anonymous subroutine generator.
Define C<TIDY> to a true value to suppress caching the extended
coroutine source code. This breaks C<copy>.
You can make another coroutine with its own pad by calling
the C<copy> method, which evals the wrapped body again.
define a C<PRE> argument to include some code to run every time
the coro is called, before going to the entry point.
define a C<DIE> argument to have C<new> tell you all about it as soon
as the body is rewritten.
When the execution falls out of the bottom of the body, an C<undef>
is returned and the execution point is reset to the begining of the
body. Variables are not cleared and will keep values from previous
times through the routine.
=head1 CAVEATS
coroutine0.pm view on Meta::CPAN
like to come back in to somewhere other than directly following your exit point.
No analysis of string literals is performed, so putting YIELD in quotes
within the body may cause problems if you didn't do it just to see the
YIELD get expanded and printed out.
We can see package variables from the calling environment but not lexicals.
=head1 FUTURE DIRECTIONS
future coroutines modules might handle recursion more gracefully, might
have a better declaration and definition syntax, might be a capability
of a more object-oriented dispatch system rather than a clumsy hack.
=head1 HISTORY
=over 8
=item 0.02
VARS is now optional
=item 0.01
Original version; created by h2xs 1.22 with options
-A -C -X -b5.0.0 -ncoroutine0 --skip-exporter
=back
=head1 SHOUT_OUTS
Damian Conway suggested the problem
Paul Kulchenko suggested this approach when I presented a much more
# Before `make install' is performed this script should be runnable with
# `make test'. After `make install' it should work as `perl 1.t'
#########################
# change 'tests => 1' to 'tests => last_test_to_print';
use Test;
BEGIN { plan tests => 16, todo => [] };
use coroutine0;
ok(1); # If we made it this far, we're ok. #'
$coderef = new coroutine0
# DIE => 1,
VARS => [qw{$number $another}],
# PRE => 'print "$number\n";',
BODY => <<'EOF',
$number = 1;
YIELD ($_[0] + $number++);
YIELD $_[0] + $number++;
YIELD ($_[0] + $number++);
EOF
PROTO => '($)';
# addn and another should be using the same pad
ok(addn 22 , 24); # test 9
# but $coderef has its own pad
ok(&$coderef(23), 24);
ok(&$another(21), 24);
# we expect \&addn to be blessed
$crefname = ref(\&addn);
ok($crefname,'coroutine0');
$cref = \&addn;
eval {
# $another_copy = copy $cref;
$another_copy = copy {\&addn};
*yet_another_copy = (\&addn)->copy();
};
ok(!$@);
ok(&$another_copy(23), 24);
ok(yet_another_copy(23), 24);
ok(&$another_copy(23), 25); # separate pad.
( run in 0.577 second using v1.01-cache-2.11-cpan-3cd7ad12f66 )