I see people using two styles for passing named parameters in Perl:
use strict;
use warnings;
use Data::Dumper;
sub foo {
print Dumper @_;
}
sub bar {
print Dumper @_;
}
foo( A => 'a', B => 'b' );
bar( { A => 'a', B => 'b' } );
What are the advantages in using foo() style instead of bar() style?
The second method passes a reference to hash, while the first just passes a list.
There are two aspects here: in theory, a reference to hash could be better in terms of performance, though for short argument lists this is negligible. For a simple call like foo(a => 1, b => 2)
there is no performance difference, because @_
is actually an alias to the original values.
But if the caller already has the values in a hash, the first style requires conversion from hash to list, and then back again to hash, which can be slow.
The second aspect is the question who is responsible for the conversion to a hash. The first style leaves it up the function being called, and if that just does my %args = @_
, it will produce curious warnings if the argument list is not of even length.
That's why I slightly prefer the second style (or I use Perl 6, which supports named arguments natively).
The foo(a => 1, b => 2)
style is the usual way of emulating named arguments. The bar({a => 1, b => 2})
is usually used only for supplementary (and possibly optional) arguments.
For typical usage, I prefer the first form. The {}
are extra typing, extra noise to read, and create a possible error if you leave out either or both braces. Any performance difference is negligible. (If it's not, you have bigger problems.) On the other hand, wrapping the arguments in an anonymous hash constructor can help you find errors at compile-time rather than runtime.
The second form is typically seen mixed with positional arguments. e.g. Benchmark does this:
cmpthese(10000, {
foo => \&foo,
bar => \&bar,
});
While Tk leaves the {}
out:
my $text = $w->Scrolled('Text', -width => 80, -height => 50);
It's usually a stylistic choice.
First, an explanation of the two methods:
sub foo {
# Transform the array to a hash
my %args = @_;
foreach my $key ( keys %args ) {
print "$key => $args{$key}\n";
}
}
# Pass an array of values
foo( A=>'a', B=>'b' );
In this first case all you're doing is passing an array. The =>
in this context is not the hash key / value indicator which you might think. In this context it's just a "fat comma".
sub bar {
my ($hash_ref) = @_;
foreach my $key ( keys %$hash_ref ) {
print "$key => $hash_ref->{$key}\n";
}
}
# pass a ref to an anonymous hash
bar( { A=>'a', B=>'b' } );
In this second case you are creating an anonymous hash and passing a reference to that hash as the argument to the function.
Why choose one over the other? In the book, Perl Best Practices, chapter 9 under the heading "Named Arguments" the author recommends using the second style when there are more than three arguments to the function. He also prefers it because it catches mismatched numbers of arguments at compile time rather than at run time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With