CPS
view release on metacpan or search on metacpan
=head2 kseq( @bodies, $k )
This CPS function takes a list of function bodies and calls them each, one at
a time in sequence. Each is given a continuation to invoke, which will cause
the next body to be invoked. When the last body has invoked its continuation,
the main continuation C<$k> is invoked.
$body->( $kdone )
$kdone->()
$k->()
A benefit of this is that it allows a long operation that uses many
continuation "pauses", to be written without code indenting further and
further to the right. Another is that it allows easy skipping of conditional
parts of a computation, which would otherwise be tricky to write in a CPS
form. See the EXAMPLES section.
=cut
sub gkseq
{
my ( $gov, @bodies ) = @_;
my $k = pop @bodies;
my $enter = $gov->can('enter') or croak "Governor cannot ->enter";
while( @bodies ) {
my $nextk = $k;
my $b = pop @bodies;
$k = sub {
@_ = ( $gov, $b, $nextk );
goto &$enter;
};
}
@_ = ();
goto &$k;
}
=head1 GOVERNORS
All of the above functions are implemented using a loop which repeatedly calls
the body function until some terminating condition. By controlling the way
this loop re-invokes itself, a program can control the behaviour of the
functions.
For every one of the above functions, there also exists a variant which takes
a L<CPS::Governor> object as its first argument. These functions use the
governor object to control their iteration.
kloop( \&body, $k )
gkloop( $gov, \&body, $k )
kforeach( \@items, \&body, $k )
gkforeach( $gov, \@items, \&body, $k )
etc...
In this way, other governor objects can be constructed which have different
running properties; such as interleaving iterations of their loop with other
IO activity in an event-driven framework, or giving rate-limitation control on
the speed of iteration of the loop.
=cut
# The above is a lie. The basic functions provided are actually the gk*
# versions; we wrap these to make the normal k* functions by passing a simple
# governor.
sub _governate
{
my $pkg = caller;
my ( $func, $name ) = @_;
my $default_gov = CPS::Governor::Simple->new;
no strict 'refs';
my $code = $pkg->can( $func ) or croak "$pkg cannot $func()";
*{$pkg."::$name"} = subname $name => sub {
unshift @_, $default_gov;
goto &$code;
};
}
_governate "g$_" => $_ for @CPS_PRIMS;
=head1 CPS UTILITIES
These function names do not begin with C<k> because they are not themselves
CPS primatives, but may be useful in CPS-oriented code.
=cut
=head2 $kfunc = liftk { BLOCK }
=head2 $kfunc = liftk( \&func )
Returns a new CODE reference to a CPS-wrapped version of the code block or
passed CODE reference. When C<$kfunc> is invoked, the function C<&func> is
called in list context, being passed all the arguments given to C<$kfunc>
apart from the last, expected to be its continuation. When C<&func> returns,
the result is passed into the continuation.
$kfunc->( @func_args, $k )
$k->( @func_ret )
The following are equivalent
print func( 1, 2, 3 );
my $kfunc = liftk( \&func );
$kfunc->( 1, 2, 3, sub { print @_ } );
Note that the returned wrapper function only has one continuation slot in its
arguments. It therefore cannot be used as the body for C<kloop()>,
C<kforeach()> or C<kgenerate()>, because these pass two continuations. There
does not exist a "natural" way to lift a normal call/return function into a
CPS function which requires more than one continuation, because there is no
way to distinguish the different named returns.
( run in 0.776 second using v1.01-cache-2.11-cpan-96521ef73a4 )