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 )