Должен ли я использовать $ _ [0] или скопировать список аргументов в Perl? - PullRequest
3 голосов
/ 18 ноября 2009

Если я передам хэш в подпрограмму:

parse(\%data);

Должен ли я сначала использовать переменную для $_[0] или можно продолжать обращаться к $_[0] всякий раз, когда я хочу получить элемент из хеша? уточнение:

sub parse
{    $var1 = $_[0]->{'elem1'};
     $var2 = $_[0]->{'elem2'};
     $var3 = $_[0]->{'elem3'};
     $var4 = $_[0]->{'elem4'};
     $var5 = $_[0]->{'elem5'};
}
# Versus
sub parse
{    my $hr = $_[0];
     $var1 = $hr->{'elem1'};
     $var2 = $hr->{'elem2'};
     $var3 = $hr->{'elem3'};
     $var4 = $hr->{'elem4'};
     $var5 = $hr->{'elem5'};
}

Является ли вторая версия более правильной, поскольку ей не нужно постоянно обращаться к массиву аргументов, или Perl в конечном итоге все равно интерпретирует их одинаково?

Ответы [ 6 ]

11 голосов
/ 18 ноября 2009

В этом случае нет разницы, потому что вы передаете ссылку на хеш. Но в случае прохождения скаляра будет разница:

sub rtrim {
    ## remove tailing spaces from first argument
    $_[0] =~ s/\s+$//;
}
rtrim($str); ## value of the variable will be changed

sub rtrim_bugged {
    my $str = $_[0]; ## this makes a copy of variable
    $str =~ s/\s+$//;
}
rtrim($str); ## value of the variable will stay the same

Если вы передаете ссылку на хеш, то создается только копия ссылки. Но сам хеш будет таким же. Поэтому, если вам небезразличен код читабельность , я предлагаю вам создать переменную для всех ваших параметров. Например:

sub parse {
     ## you can easily add new parameters to this function
     my ($hr) = @_; 

     my $var1 = $hr->{'elem1'};
     my $var2 = $hr->{'elem2'};
     my $var3 = $hr->{'elem3'};
     my $var4 = $hr->{'elem4'};
     my $var5 = $hr->{'elem5'};
}

Также более понятные имена переменных также улучшат ваш код.

7 голосов
/ 18 ноября 2009

Для общего обсуждения эффективности shift по сравнению с прямым доступом к @_ см .:

Что касается вашего конкретного кода, я бы использовал shift, но упростил бы извлечение данных с помощью фрагмента хеша:

sub parse
{
    my $hr = shift;
    my ($var1, $var2, $var3, $var4, $var5) = @{$hr}{qw(elem1 elem2 elem3 elem4 elem5)};
}

Я предполагаю, что этот метод делает что-то еще с этими переменными, что делает целесообразным хранить их в отдельных переменных (возможно, хеш доступен только для чтения, и вам нужно внести некоторые изменения, прежде чем вставлять их в некоторые другие данные? ) - иначе, почему бы просто не оставить их в хэшрефе, с которого они начали?

5 голосов
/ 18 ноября 2009

Вы микрооптимизируете; попытаться избежать этого. Пойдите с тем, что наиболее читабельно / ремонтопригодно. Обычно это будет та, где вы используете лексическую переменную, поскольку ее имя указывает на ее назначение ... но если вы используете имя типа $data или $x, это, очевидно, неприменимо.

С точки зрения технических деталей, для большинства целей вы можете оценить время, затрачиваемое путем подсчета количества основных операций, которые Perl будет использовать. Для вашего $_[0] поиск элемента в нелексической переменной массива занимает несколько операций: один для получения глоба, один для получения части массива массива, один или несколько для получения индекса (только один для константы) и один, чтобы посмотреть элемент. $hr, с другой стороны, это одна операция. Чтобы обслуживать прямых пользователей @_, существует оптимизация, которая сокращает количество операций для $_[0] до единой объединенной операции (когда индекс составляет от 0 до 255 включительно), но в вашем случае она не используется, потому что Контекст deref требует дополнительного флага при поиске элемента массива (для поддержки автовивификации), и этот флаг не поддерживается оптимизированной операцией.

Таким образом, использование лексического будет и более читабельным, и (если вы используете его более одного раза) незаметно быстрее.

4 голосов
/ 18 ноября 2009

Мое правило: я стараюсь не использовать $_[0] в подпрограммах, которые длиннее пары операторов. После этого все получает пользовательскую переменную.

Почему вы копируете все значения хеш-функции в переменные? Просто оставьте их в хеше, где они принадлежат. Это намного лучшая оптимизация, чем та, о которой вы думаете.

0 голосов
/ 18 ноября 2009

Поскольку они работают, оба в порядке, обычная практика - shift отключить параметры.

sub parse { my $hr = shift; my $var1 = $hr->{'elem1'}; }
0 голосов
/ 18 ноября 2009

То же самое, хотя вторая более ясна

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...