NAME returning - define subs that act like "return" SYNOPSIS use Test::Simple tests => 1; use returning { Yes => 1, No => 0, }; sub beats_sissors { local $_ = shift; No if /paper/i; Yes if /rock/i; No if /scissors/; } ok beats_scissors("rock"); DESCRIPTION The "returning" module allows you to define subs which act like "return". That is, they break out of their caller sub. In the SYNPOSIS example, the "/scissors/i" regexp is never even evaluated because the "Yes" statement breaks out of the the sub, returning "1". The "beats_scissors" function could have alternatively been written as: sub beats_sissors { local $_ = shift; return 0 if /paper/i; return 1 if /rock/i; return 0 if /scissors/; } "returning" may be especially useful for domain-specific languages. Usage There are three ways to define a returning sub using this module: use returning { subname => 'value' }; This creates the sub in the caller's namespace called " subname " with an empty prototype. (So when calling the sub, you don't need to use parentheses; just like with constant subs, but without as much optimization.) use returning { subname => sub { ... } } This installs the provided sub into the caller's namespace. This allows you to define non-constant subs, including subs that take parameters and do interesting stuff with them. BEGIN { sub subname { ... } }; use returning 'subname'; # look, no hashref! This does not install any sub into the caller's namespace, but modifies an existing sub to act in a returning way. Note that because "use" operates at compile time, you need to take a lot of care to ensure that the sub has already been defined. These can be combined, a la... use constant ZeroButTrue => '0E0'; use returning 'ZeroButTrue', { Affirm => !!1, Deny => !!0, Mu => sub { return; }, } Implementation Notes My first stab at this used Devel::Declare, but I couldn't quite get it working, and nobody in "#devel-declare" seemed sure why it was not. It seems possible that the ability to do this lies slightly beyond what Devel::Declare is capable of. Instead Scope::Upper has been used to create wrappers which jump up one more subroutine than expected when they return. This means that some of the magic happens at run-time rather than compile-time, so it perhaps executes slightly slower, but probably compiled slightly faster. An advantage of Scope::Upper is that you can re-export your "returning" subs to other packages with no problem, and they'll continue to have their special behaviour with no extra effort. A feature I had been hoping to achieve with Devel::Declare would be for calling a sub with an ampersand ("&Affirm()") to act as a way of avoiding the magic behaviour. This has not been possible with Scope::Upper. Class Method "returning->setup_for($package, $subname)" Given the package name and subname of an *existing* sub, sets up the magic. BUGS Please report any bugs to <http://rt.cpan.org/Dist/Display.html?Queue=returning>. SEE ALSO "Scope::Upper" takes care of most of the black magic. AUTHOR Toby Inkster <tobyink@cpan.org>. CREDITS Thanks OSFAMERON, Matt S Trout (MSTROUT), and Ash Berlin (ASH), for helping me through some of the tricky bits. COPYRIGHT AND LICENCE This software is copyright (c) 2012 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.