File Coverage

blib/lib/Sub/Become.pm
Criterion Covered Total %
statement 21 21 100.0
branch 1 2 50.0
condition 1 3 33.3
subroutine 7 7 100.0
pod 1 1 100.0
total 31 34 91.1


line stmt bran cond sub pod time code
1             package Sub::Become;
2              
3 2     2   46978 use warnings;
  2         6  
  2         76  
4 2     2   12 use strict;
  2         5  
  2         63  
5 2     2   10 use Carp;
  2         8  
  2         313  
6 2     2   12 use base qw( Exporter );
  2         3  
  2         862  
7              
8             our @EXPORT_OK = our @EXPORT = qw( become );
9              
10             =head1 NAME
11              
12             Sub::Become - Syntactic sugar to allow a sub to replace itself
13              
14             =head1 VERSION
15              
16             This document describes Sub::Become version 0.01
17              
18             =cut
19              
20             our $VERSION = '0.01';
21              
22             =head1 SYNOPSIS
23              
24             use Sub::Become;
25            
26             sub foo {
27             my $t = Date->new();
28             become {
29             return $t;
30             }
31             return foo();
32             }
33            
34             =head1 DESCRIPTION
35              
36             A useful technique in languages like JavaScript is to write a function
37             that replaces its own definition:
38              
39             var foo = function() {
40             var t = new Date();
41             foo = function() {
42             return t;
43             };
44             return foo();
45             };
46              
47             See L for a complete explanation
48             of the technique.
49              
50             C provides a little syntactic sugar to make this
51             easy in Perl too. See the SYNOPSIS for an example.
52              
53             =head1 INTERFACE
54              
55             =head2 C<< become >>
56              
57             Replace the current subroutine with the supplied code block:
58              
59             sub bar {
60             become { 2 }; # return 2 next time
61             return 1; # return 1 first time
62             }
63              
64             If you need to return the value that the new subroutine definition would
65             have returned in the same invocation either have the subroutine recurse:
66              
67             sub expensive {
68             my $thing = some_expensive_calculation();
69             become { $thing };
70             return expensive();
71             }
72              
73             Or exploit the fact that C returns the code reference for the
74             new definition:
75              
76             sub expensive {
77             my $thing = some_expensive_calculation();
78             return (become { $thing })->();
79             }
80              
81             =cut
82              
83             sub become(&) {
84 3 50 33 3 1 3437 croak "become needs a coderef"
85             unless @_ == 1 && 'CODE' eq ref $_[0];
86 2     2   13 no strict 'refs';
  2         4  
  2         76  
87 2     2   11 no warnings 'redefine';
  2         4  
  2         252  
88 3         6 return *{ ( caller 1 )[3] } = shift;
  3         37  
89             }
90              
91             1;
92             __END__