Callback-Frame

 view release on metacpan or  search on metacpan

lib/Callback/Frame.pm  view on Meta::CPAN

    say $foo;     # 1
    say $cb->();  # 1  <- not 2!
    say $foo;     # 1

Here's a way to "fix" that using Callback::Frame:

    our $foo = 1;
    my $cb;

    frame_local __PACKAGE__.'::foo', sub {
      $foo = 2;
      $cb = fub {
        return $foo;
      };
    };

    say $foo;     # 1
    say $cb->();  # 2  <- hooray!
    say $foo;     # 1

Don't be fooled into thinking that this is a lexical binding though. While the callback C<$cb> is executing, all parts of the program will see the binding containing C<2>:

    our $foo = 1;
    my $cb;

    sub global_foo_getter {
      return $foo;
    }

    frame_local __PACKAGE__.'::foo', sub {
      $foo = 2;
      $cb = fub {
        return global_foo_getter();
      };
    };

    say $foo;     # 1
    say $cb->();  # 2  <- still 2
    say $foo;     # 1

You can install multiple local variables in the same frame with the C<frame> interface:

    frame(local => __PACKAGE__.'::foo',
          local => 'main::bar',
          code => { })->();

Note that if you have both C<catch> and C<local> elements in a frame, in the event of an error the local bindings will B<not> be present inside the C<catch> handler (use a nested frame if you need this).

Variable names must be fully package qualified. The best way to do this for variables in your current package is to use the ugly C<__PACKAGE__> technique.

Objects stored in local bindings managed by Callback::Frame will not be destroyed until all references to the frame-wrapped callback that contains the binding are destroyed, along with all references to any deeper frames.



=head1 SEE ALSO

L<The Callback::Frame github repo|https://github.com/hoytech/Callback-Frame>

L<AnyEvent::Task> uses Callback::Frame and its docs have more discussion on exception handling in async apps.

This module's C<catch> syntax is of course modeled after "normal language" style exception handling as implemented by L<Try::Tiny> and similar.

This module depends on L<Guard> to maintain the C<$Callback::Frame::active_frames> datastructure and to ensure that C<local> binding updates aren't lost even when exceptions or other non-local returns occur.

L<AnyEvent::Debug> provides an interactive debugger for AnyEvent applications and uses some of the same techniques that Callback::Frame does. L<AnyEvent::Callback> and L<AnyEvent::CallbackStack> sort of solve the dynamic error handler problem. Unlike...

L<Promises> and L<Future> are similar modules but they solve a slightly different problem. In the area of exception handling they require a more drastic restructuring of your async code because you need to pass "promise/future" objects around to main...

Miscellaneous other modules: L<IO::Lambda::Backtrace>, L<POE::Filter::ErrorProof>

Python Tornado's L<StackContext|http://www.tornadoweb.org/en/branch2.3/stack_context.html> and C<async_callback>

L<Let Over Lambda, Chapter 2|http://letoverlambda.com/index.cl/guest/chap2.html>

L<UNWIND-PROTECT vs. Continuations|http://www.nhplace.com/kent/PFAQ/unwind-protect-vs-continuations-original.html>



=head1 BUGS

For now, C<local> bindings can only be created in the scalar namespace. Also, none of the other nifty things that L<local> can do (like localising a hash table value) are supported yet.



=head1 AUTHOR

Doug Hoyte, C<< <doug@hcsw.org> >>

=head1 COPYRIGHT & LICENSE

Copyright 2012-2016 Doug Hoyte.

This module is licensed under the same terms as perl itself.

=cut



TODO:

  * frame_try should check to see what context it is being called on and preserve this for its try callback



( run in 2.253 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )