Я вижу людей, использующих два стиля для передачи именованных параметров в 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' } );
Каковы преимущества использования стиля foo() вместо стиля bar()?
Второй метод передает ссылку на хэш, а первый просто передает список.
Здесь есть два аспекта: теоретически ссылка на хэш могла бы быть лучше с точки зрения производительности, хотя для коротких списков аргументов это незначительно. Для простого вызова, такого как foo(a => 1, b => 2), разницы в производительности нет, потому что @_ на самом деле является псевдонимом исходных значений.
Но если у вызывающего уже есть значения в хэше, первый стиль требует преобразования из хэша в список, а затем обратно в хеш, что может быть медленным.
Второй аспект - это вопрос, кто отвечает за преобразование в хэш. Первый стиль оставляет вызываемую функцию наверху, и если это просто делает my %args = @_, он выдаст любопытные предупреждения, если список аргументов имеет нечетную длину.
Вот почему я немного предпочитаю второй стиль (или я использую Perl 6, который изначально поддерживает именованные аргументы).
Ответ 2 · рейтинг 6 · Michael Carman
Стиль foo(a => 1, b => 2) - это обычный способ эмуляции именованных аргументов. bar({a => 1, b => 2}) обычно используется только для дополнительных (и, возможно, необязательных) аргументов.
Для типичного использования я предпочитаю первую форму. {} - это лишний набор текста, лишний шум при чтении и создание возможной ошибки, если вы пропустите одну или обе фигурные скобки. Любая разница в производительности незначительна. (Если это не так, у вас большие проблемы.) С другой стороны, помещение аргументов в анонимный хэш-конструктор может помочь вам найти ошибки во время компиляции, а не во время выполнения.
Вторая форма обычно встречается в сочетании с позиционными аргументами. например Бенчмарк делает это:
cmpthese(10000, {
foo => \&foo,
bar => \&bar,
});
В то время как Tk оставляет {} вне:
my $text = $w->Scrolled('Text', -width => 80, -height => 50);
Обычно это стилистический выбор.
Ответ 3 · рейтинг 5 · Robert S. Barnes
Во-первых, объяснение двух методов:
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' );
В этом первом случае все, что вы делаете, это передаете массив. => в этом контексте не является индикатором ключа/значения хэша, как вы могли бы подумать. В данном контексте это просто "жирная запятая".
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' } );
Во втором случае вы создаете анонимный хэш и передаете ссылку на этот хеш в качестве аргумента функции.
Зачем выбирать одно над другим? В книге Perl Best Practices, глава 9 под заголовком "Именованные аргументы", автор рекомендует использовать второй стиль, когда у функции более трех аргументов. Он также предпочитает его, потому что он улавливает несоответствие количества аргументов во время компиляции, а не во время выполнения.