- closure
Closures
A subroutine that generates subroutines based on some input values.
examples/references/incrementer.pl
#!/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; }
examples/references/incrementer-generator.pl
#!/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
examples/functional/Transformers.pm
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;
examples/functional/add_logging.pl
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);
examples/functional/add_logging_replace.pl
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";