'Действительно ли сдвиг' является злым для обработки параметров подпрограммы Perl?

В дополнение к уже упомянутому

 теги, необходимо также использовать @code аннотация JavaDoc, которая сделает жизнь намного легче когда дело доходит до проблем объектов HTML (в особенности с Дженериками), например: 
* 
* {@code
* Set s;
* System.out.println(s);
* }
* 

даст корректный вывод HTML:

Set s;
System.out.println(s);

В то время как исключение @code блок (или использование тег) приведут к HTML как это:

Set s;
System.out.println(s);

(Для ссылки, Java SE 8 описаний тега могут быть найдены здесь: Теги Javadoc )

27
задан brian d foy 25 August 2009 в 23:09
поделиться

8 ответов

Использование shift для распаковки аргументов не является злом. Это обычное соглашение, которое может быть самым быстрым способом обработки аргументов (в зависимости от того, сколько их и как они передаются). Вот один пример довольно распространенного сценария, в котором это так: простой аксессор.

use Benchmark qw(cmpthese);

sub Foo::x_shift { shift->{'a'} }
sub Foo::x_ref   { $_[0]->{'a'} }
sub Foo::x_copy  { my $s = $_[0]; $s->{'a'} }

our $o = bless {a => 123}, 'Foo';

cmpthese(-2, { x_shift => sub { $o->x_shift },
               x_ref   => sub { $o->x_ref   },
               x_copy  => sub { $o->x_copy  }, });

Результаты perl 5.8.8 на моей машине:

            Rate  x_copy   x_ref x_shift
x_copy  772761/s      --    -12%    -19%
x_ref   877709/s     14%      --     -8%
x_shift 949792/s     23%      8%      --

Не драматичны, но вот они. Всегда проверяйте свой сценарий на своей версии Perl на целевом оборудовании, чтобы узнать наверняка.

shift также полезен в тех случаях, когда вы хотите отключить инвокант, а затем вызвать SUPER :: , передав оставшиеся @_ как есть.

sub my_method
{
  my $self = shift;
  ...
  return $self->SUPER::my_method(@_);
}

Если бы у меня была очень длинная серия операций my $ foo = shift; в верхней части функции, Однако, Вместо этого я мог бы рассмотреть возможность использования массовой копии из @_ . Но в целом, если у вас есть функция или метод, который принимает более нескольких аргументов, используя именованные параметры (т. Е. Перехват всех @_ в хэше % args или ожидание один аргумент ссылки на хэш) - гораздо лучший подход.

50
ответ дан 28 November 2019 в 04:11
поделиться

Это, как и другие сказал, дело вкуса.

Я обычно предпочитаю переносить мои параметры в лексические, потому что это дает мне стандартное место для объявления группы переменных, которые будут использоваться в подпрограмме. Дополнительная многословность дает мне хорошее место для комментариев. Это также упрощает аккуратное предоставление значений по умолчанию.

sub foo {
    my $foo = shift;       # a thing of some sort.
    my $bar = shift;       # a horse of a different color.
    my $baz = shift || 23; # a pale horse.

    # blah
}

Если вас действительно беспокоит скорость вызова ваших подпрограмм, не делайте этого. t вообще распаковывать аргументы - обращаться к ним напрямую, используя @_ . Будьте осторожны, это ссылки на данные вызывающего абонента, с которыми вы работаете. Это обычная идиома в POE. POE предоставляет набор констант, которые вы используете для получения позиционных параметров по имени:

sub some_poe_state_handler {
    $_[HEAP]{some_data} = 'chicken';
    $_[KERNEL]->yield('next_state');
}

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

sub foo {
    my $foo = shift;
    my $bar = shift;
    my @baz = shift;

    # I should really stop coding and go to bed.  I am making dumb errors.

}

Я думаю, что согласованный стиль кода более важен чем какой-либо конкретный стиль. Если бы все мои коллеги использовали стиль назначения списков, я бы тоже использовал его.

Если бы мои коллеги сказали, что с использованием shift для распаковки возникла большая проблема, я бы попросил продемонстрировать, почему это плохо. Если корпус прочный, то кое-что узнаю. Если это подделка, я мог бы опровергнуть его и помочь остановить распространение анти-знания. Затем я' Я предлагаю определить стандартный метод и следовать ему в будущем коде. Я мог бы даже попытаться установить политику Perl :: Critic, чтобы проверить соответствие принятому стандарту.

11
ответ дан 28 November 2019 в 04:11
поделиться

Perl :: Critic - ваш друг. Он соответствует «стандартам», установленным в книге Дэмиана Конвея Perl Best Practices. Запуск с --verbose 11 дает вам объяснение того, почему все плохо. Не распаковывать @_ первым в ваших подпрограммах имеет степень серьезности 4 (из 5). Например:

echo 'package foo; use warnings; use strict; sub quux { my foo= shift; my (bar,baz) = @_;};1;' | perlcritic -4 --verbose 11

Always unpack @_ first at line 1, near 'sub quux { my foo= shift; my (bar,baz) = @_;}'.
  Subroutines::RequireArgUnpacking (Severity: 4)
    Subroutines that use `@_' directly instead of unpacking the arguments to
    local variables first have two major problems. First, they are very hard
    to read. If you're going to refer to your variables by number instead of
    by name, you may as well be writing assembler code! Second, `@_'
    contains aliases to the original variables! If you modify the contents
    of a `@_' entry, then you are modifying the variable outside of your
    subroutine. For example:

       sub print_local_var_plus_one {
           my ($var) = @_;
           print ++$var;
       }
       sub print_var_plus_one {
           print ++$_[0];
       }

       my $x = 2;
       print_local_var_plus_one($x); # prints "3", $x is still 2
       print_var_plus_one($x);       # prints "3", $x is now 3 !
       print $x;                     # prints "3"

    This is spooky action-at-a-distance and is very hard to debug if it's
    not intentional and well-documented (like `chop' or `chomp').

    An exception is made for the usual delegation idiom
    `$object->SUPER::something( @_ )'. Only `SUPER::' and `NEXT::' are
    recognized (though this is configurable) and the argument list for the
    delegate must consist only of `( @_ )'.
1
ответ дан 28 November 2019 в 04:11
поделиться

По своей сути это не зло, но его использование для получения аргументов подпрограммы один за другим сравнительно медленно и требует большего количества строк кода.

0
ответ дан 28 November 2019 в 04:11
поделиться

Имеется оптимизация для назначения списков.

Единственная ссылка, которую я смог найти, это этот .

5.10.0 случайно отключил оптимизация, которая вызвала измеримое падение производительности в списке назначение, такое как часто используется для назначить параметры функции из @_ . Оптимизация восстановлена, и исправлена ​​регрессия производительности.

Это пример затронутой регрессии производительности.

sub example{
  my($arg1,$arg2,$arg3) = @_;
}
1
ответ дан 28 November 2019 в 04:11
поделиться

Это не зло, это своего рода вкус. Вы часто будете видеть стили, используемые вместе:

sub new {
    my $class = shift;
    my %self = @_;
    return bless \%self, $class;
}

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

20
ответ дан 28 November 2019 в 04:11
поделиться

и должны работать нормально, в Википедии есть Список предопределенных сущностей в XML .

кто догматично использует первую форму (возможно, они думают, что shift - зло) редактирует ваш файл и рассеянно обновляет его до чтения

sub do_another_thing {
  my ($foo, $bar)  = shift; # still 'works', but $bar not defined
}

, и они, возможно, внесли тонкую ошибку.

Назначение @_ может быть более компактным и эффективным с вертикальным пространством, когда у вас есть небольшое количество параметров для одновременного назначения. Это также позволяет вам указывать аргументы по умолчанию, если вы используете хэш-стиль именованных параметров функции

например

 my (%arguments) = (user=>'defaultuser',password=>'password',@_);

Я все равно считаю это вопросом стиля / вкуса. Я считаю, что самое важное - применять тот или иной стиль последовательно, соблюдая принцип наименьшего удивления.

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

, например,

 my (%arguments) = (user=>'defaultuser',password=>'password',@_);

Я все равно считаю это вопросом стиля / вкуса. Я считаю, что самое важное - применять тот или иной стиль последовательно, соблюдая принцип наименьшего удивления.

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

например

 my (%arguments) = (user=>'defaultuser',password=>'password',@_);

Я все равно считаю это вопросом стиля / вкуса. Я думаю, что самое важное - применять тот или иной стиль последовательно, соблюдая принцип наименьшего удивления.

8
ответ дан 28 November 2019 в 04:11
поделиться

Я не думаю, что shift - зло. Использование shift показывает вашу готовность именовать переменные вместо использования $ _ [0] .

Лично Я использую shift , когда у функции только один параметр. Если у меня более одного параметра, я буду использовать контекст списка.

 my $result = decode($theString);

 sub decode {
   my $string = shift;

   ...
 }

 my $otherResult = encode($otherString, $format);

 sub encode {
   my ($string,$format) = @_;
   ...
 }
1
ответ дан 28 November 2019 в 04:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: