\
operator to create a reference.
my $sref = \$scalar;
my $aref = \@array;
my $aref2 = [ 1, 2, 3 ];
my $href = \%hash;
my $href2 = { a => 1, b => 2 };
my $cref = \&func;
print "${$sref}\n";
my $len = @{$aref};
$aref->[0] = 15;
my $keyscnt = keys %{$href};
$href->{'c'} = 3;
perldoc perlreftut
)perldoc perlref
)perldoc perllol
)perldoc perldsc
)sub
operator.sub
operator returns a coderef.
sub sum
{
my $sum = shift;
$sum += $_ foreach @_;
return $sum;
}
my $sumref = \∑
print $sumref->( 1..6 ), "\n";
my $sumref = sub
{
my $sum = shift;
$sum += $_ foreach @_;
return $sum;
};
print $sumref->( 1..6 ), "\n";
You can also call through a coderef like this:
&{$cref}( 1..6 );
I really don't like this style, but it's here for completeness.
Why use coderefs?
sort
, map
, grep
@list = sort { $b <=> $a } @list;
sub backwards { return $b cmp $a; }
@list = sort backwards @list;
The code in the curlies is actually a coderef. Also can use the name of a subroutine.
my $quit_btn = $window->Button(
'-text' => "Quit",
'-command' => sub { exit( 0 ); }
);
Supplying a callback to be executed when the button is clicked.
How do you do things generically with complex data structures?
Let's do this with a concrete example: a hierarchical filesystem
sub find_large_files
{
my ($dir, $size) = @_;
my @files = grep { -s $_ > $size } $dir->files();
foreach my $d ($dir->dirs())
{
push @files, find_large_files( $d, $size );
}
return @files;
}
sub find_small_files
{
my ($dir, $size) = @_;
my @files = grep { -s $_ < $size } $dir->files();
foreach my $d ($dir->dirs())
{
push @files, find_small_files( $d, $size );
}
return @files;
}
sub grep_files
{
my ($dir, $cref) = @_;
my @files = grep { $cref->( $_ ) } $dir->files();
foreach my $d ($dir->dirs())
{
push @files, grep_files( $d, $cref );
}
return @files;
}
my @large_files =
grep_files( $dir, sub { -s $[0] > $bigsize } );
my @small_files =
grep_files( $dir, sub { -s $[0] < $smallsize } );
foreach my $cref (@code)
{
@data = $cref->( @data );
}
Notice that we are looping over the code routines not over the data.
Part of a four-function calculator.
my %operations = (
'+' => sub { return $_[0] + $_[1]; },
'-' => sub { return $_[0] - $_[1]; },
'*' => sub { return $_[0] * $_[1]; },
'/' => sub { return $_[0] / $_[1]; },
'q' => sub { exit( 0 ); },
);
You could actually map any strings. Good also for language-based interfaces.
my $obj = {
'name' => 'Fred',
'age' => 37,
'command' => sub { return $_[0] * 2; },
};
Hard to come up with a generic example of this. I have used it several times, so it's funny that I can't come up with a good example.
foreach my $file (@files)
{
if($is_relative)
{
push @files, $file
if -s "$base_dir$file" > $size;
}
else
{
push @files, $file
if -s $file > $size;
}
}
Notice that the condition will be tested for each item in the list. For a complex conditional, this could be expensive. Worse, if there are multiple conditions, the code would be really hard to understand.
my $test;
if($is_relative)
{
$test = sub { -s "$base_dir$_[0]" > $size ? ($_[0]) : () };
}
else
{
$test = sub { -s $_[0] > $size ? ($_[0]) : () };
}
foreach my $file (@files)
{
push @files, $test->( $file );
}
The code doesn't look much smaller. However, the conditions at the beginning are not executed every time. We can also move this code elsewhere to make this code easier to maintain.
sub make_multiplier
{
my $factor = shift;
return sub { return shift * $factor; };
}
my $doubler = make_multiplier( 2 );
my $tripler = make_multiplier( 3 );
This seems to be the way most people introduce closures. Not because it is particularly useful or realistic. I think it is just easy to understand.
sub add { return $_[0] + $_[1]; }
sub bind_second
{
my $coderef = shift;
my $second = shift;
return sub { return $_[0] + $second; };
}
my $inc = bind_second( \&add, 1 );
Once again, not particularly useful, but it is easy to understand.