CPS
view release on metacpan or search on metacpan
This allows running multiple operations in parallel, and waiting for
them all to complete before continuing. It provides in a CPS form
functionality similar to that provided in a more object-oriented
fashion by modules such as Async::MergePoint or Event::Join.
kpareach( \@items, \&body, $k )
This CPS function takes a list of items and a function body, and calls
the body immediately once for each item in the list. Each invocation is
given its own continuation. Once every body has invoked its
continuation, the main continuation $k is invoked.
$body->( $item, $kdone )
$kdone->()
$k->()
This is similar to kforeach, except that the body is started
concurrently for all items in the list list, rather than each item
waiting for the previous to finish.
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 $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.
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 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.
CPS UTILITIES
These function names do not begin with k because they are not
themselves CPS primatives, but may be useful in CPS-oriented code.
$kfunc = liftk { BLOCK }
$kfunc = liftk( \&func )
Returns a new CODE reference to a CPS-wrapped version of the code block
or passed CODE reference. When $kfunc is invoked, the function &func is
called in list context, being passed all the arguments given to $kfunc
apart from the last, expected to be its continuation. When &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 kloop(),
kforeach() or 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.
$func = dropk { BLOCK } $kfunc
$func = dropk $waitfunc, $kfunc
Returns a new CODE reference to a plain call/return version of the
passed CPS-style CODE reference. When the returned ("dropped") function
is called, it invokes the passed CPS function, then waits for it to
invoke its continuation. When it does, the list that was passed to the
continuation is returned by the dropped function. If called in scalar
context, only the first value in the list is returned.
$kfunc->( @func_args, $k )
$k->( @func_ret )
$waitfunc->()
@func_ret = $func->( @func_args )
Given the following trivial CPS function:
$kadd = sub { $_[2]->( $_[0] + $_[1] ) };
The following are equivalent
$kadd->( 10, 20, sub { print "The total is $_[0]\n" } );
( run in 1.610 second using v1.01-cache-2.11-cpan-71847e10f99 )