Closures help improve code by providing a flexible, largely declarative way to implement re-usable code. This talk looks at the basic of closures using Perl5 and shows some ways they can provide nice solutions to common problems in any language.
my $final = shift // 2**32-1; looks_like_number $value or die ... ; looks_like_number $final or die ... ; $value <= $final or die ... ; sub { $value > $final and return; $value++ } } anonymous subs & subref’s can be passed as arguments.
my $final = shift // 2**32-1; looks_like_number $value or die ... ; looks_like_number $final or die ... ; $value <= $final or die ... ; sub { $value > $final and return; $value++ } } Dynamic subroutine closes over $value & $final.
my $final = shift // 2**32-1; looks_like_number $value or die ... ; looks_like_number $final or die ... ; $value <= $final or die ... ; sub { $value > $final and return; $value++ } } Dynamic subroutine closes over $value & $final. Each instance has its own variables.
my $three_digit = generate_counter 100, 999 ; for(;;) { my $row = read_something; my $id = $two_digit->() // die ‘Exhausted two digit’; ... } Generate a counter as closure and use the values.
$SIG{ INT } = ... ; say ‘Enter a name:’ || die “Failed say.\n”; my $name = readline // die “Failed readline.\”; length $name > 6 or die “Too short: ‘$name’”; $name =~ m{ \s }x and die ‘Sorry, no whitespace’;
} = ... ; say ‘Enter a name:’ || die “Failed say.\n”; my $name = readline // die “Failed readline.\”; length $name > 6 or die “Too short: ‘$name’”; $name =~ m{ \s }x and die ‘Sorry, no whitespace’;
{ my ( $prompt, $sanity ) = @_; local $SIG{ INT } = ... ; say $prompt || die “Failed say.\n”; my $input = readline // die “Failed readline.\”; $input->$sanity or die “Botched input.\n”; }
my ( $prompt, $sanity ) = @_; local $SIG{ INT } = ... ; say $prompt || die “Failed say.\n”; my $input = readline // die “Failed readline.\”; $input->$sanity or die “Botched input.\n”; }
$sanity = date_sanity $cutoff; sub date_sanity { my $first = shift; sub { my $val = shift; my $time = str2time $val or die “Bogus date $val\n”; $time < $first or die “$val < $first\n”; }
... ; my $name_check = name_sanity ... ; my $path_check = path_sanity ... ; my $date = get_input Date => $date_sanity; my $name = get_input Name => $name_sanity; my $path = get_input Path => $path_sanity;
= @_; my $continue = ‘’; my $handler = sub { $continue = ‘’ }; sub { $continue = 1; local $SIG{ INT } = $handler ; for( my $val ; $continue ; ) { $val = eval { say $prompt // die ... my $input = readline or die ... $input->$sanity or die ... } // next; return input; } } } Caller passes prompt and sanity check. Gets back an input handler as a closure.