FP::Trampoline -- tail call optimization without reliance on goto


    use FP::Trampoline; # exports `T` and `trampoline`

    sub iterative_fact {
        my ($n,$tot)= @_;
        $n > 1 ? T{ iterative_fact ($n-1, $tot*$n) } : $tot
        # or
        # $n > 1 ? TC *iterative_fact, $n-1, $tot*$n : $tot
    sub fact {
        my ($n)=@_;
        trampoline iterative_fact ($n, 1)
    is fact(5), 120;

    use FP::Stream;
    is( fact(20), stream_iota(2)->take(19)->product );


Perl has direct support for optimized (i.e. non-stack-eating) tail calls, by way of `goto &$subref`, but there are still bugs in current versions of Perl with regards to memory handling in certain situations (see "perl/goto-leak" in t). Trampolining is a technique that works without reliance on any tail call optimization support by the host language. Its drawbacks are more overhead and the requirement to put a `trampoline`ing call around any function that employs trampolining.


T { ... }

Returns a closure blessed into the `FP::Trampoline::Continuation` namespace, which represents a trampolining continuation.

TC $fn, $arg1...

Returns a `FP::Trampoline::Call` object, which represents the same thing, but can only be used for a call ('Trampoline Call'). The advantage is that the arguments for the call are evaluated eagerly, which makes it work for dynamic variables, too (like `$_` or local'ized globals). It may also be a bit faster.

trampoline ($value)

The trampoline that bounces back as long as it receives a trampolining continuation: if so, the continuation is run, and the result passed to the `trampoline` again, otherwise it is returned directly.


This is alpha software! Read the status section in the package README or on the website.