Closures
-
closure
A subroutine that generates subroutines based on some input values.
#!/usr/bin/perl
use strict;
use warnings;
sub incrementer {
my $old = $_[0];
$_[0] += $_[1];
return $old;
}
my $x = 23;
my $old = incrementer($x, 19);
print "$old $x\n"; # 23 42
sub incrementer_23 {
my $inc = 23;
my $old = $_[0];
$_[0] += $inc;
return $old;
}
#!/usr/bin/perl
use strict;
use warnings;
sub incrementer_generator {
my ($inc) = @_;
return sub {
my $old = $_[0];
$_[0] += $inc;
return $old;
}
}
my $inc19 = incrementer_generator(19);
my $x = 23;
my $old_value = $inc19->($x);
print "$x\n";
print "old after inc19: $old_value\n";
my $inc5 = incrementer_generator(5);
print "old after inc5: " . $inc5->($x) . "\n";
print "$x\n";
my $prev_value = $inc19->($x);
print "old after inc19: $prev_value\n";
print "$x\n";
Output:
42
old after inc19: 23
old after inc5: 42
47
old after inc19: 47
66
package Transformers;
use strict;
use warnings;
use Time::HiRes qw(time);
use Exporter qw(import);
our @EXPORT_OK = qw(show_elapsed_time);
sub show_elapsed_time {
my (@subs) = @_;
my $caller = caller();
for my $sub (@subs) {
my $name = "${caller}::$sub"; # fully qualified name
no strict 'refs';
my $subref = \&$name;
my $new = sub {
my $start = time;
my (@results, $result);
if (wantarray) {
@results = $subref->(@_);
} elsif (defined wantarray) {
$result = $subref->(@_);
} else {
$subref->(@_);
}
my $end = time;
my $elapsed = $end - $start;
print "Elapsed time of $name: $elapsed\n";
return wantarray ? @results : $result;
};
no warnings 'redefine';
*{$name} = $new;
}
return;
}
1;
use strict;
use warnings;
sub count {
my ($limit) = @_;
print "count till $limit\n";
my $counter = 0;
$counter++ while $counter < $limit;
}
sub show_elapsed {
my ($sub) = @_;
use Time::HiRes qw(time);
return sub {
my $start = time;
$sub->(@_);
my $end = time;
my $elapsed = $end - $start;
print "Elapsed time: $elapsed\n";
}
}
my $newcount = show_elapsed(\&count);
$newcount->(10000000);
#*count = $newcount;
count(10000000);
use strict;
use warnings;
use lib '.';
use Transformers qw(show_elapsed_time);
show_elapsed_time('count', 'add', 'calc');
sub count {
my ($limit) = @_;
print "count till $limit\n";
my $counter = 0;
$counter++ while $counter < $limit;
}
sub add {
my ($x, $y) = @_;
print "Add $x + $y\n";
return $x+$y;
}
sub calc {
my ($x, $y) = @_;
print "Calc $x $y\n";
return $x+$y, $x*$y;
}
count(10000000);
my $res = add(2, 3);
print "Res: $res\n";
my @res = calc(2, 3);
print "Res: @res\n";