Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Стиль передачи параметров в Perl

Автор вопроса: HowardОтветов: 3

Я вижу людей, использующих два стиля для передачи именованных параметров в 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()?

parametersperl

Ответы

Ответ 1 · рейтинг 9 · moritz

Второй метод передает ссылку на хэш, а первый просто передает список.

Здесь есть два аспекта: теоретически ссылка на хэш могла бы быть лучше с точки зрения производительности, хотя для коротких списков аргументов это незначительно. Для простого вызова, такого как 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 под заголовком "Именованные аргументы", автор рекомендует использовать второй стиль, когда у функции более трех аргументов. Он также предпочитает его, потому что он улавливает несоответствие количества аргументов во время компиляции, а не во время выполнения.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы