Perl - передающие аргументы подпрограмме как проблема пар "ключ-значение" хеша

== оператор имеет совершенно особое свойство, которое создает это тревожащее равенство (Да, я знаю на других динамических языках как Perl, это поведение ожидалось бы, но JavaScript ususally не пытается быть умным в сравнениях):

>>> 1 == true
true
>>> 0 == false
true
>>> 2 == true
false
5
задан kk. 1 December 2009 в 10:26
поделиться

1 ответ

Пояснения

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

Подготовка: ваши входные данные

@array = (“0A0”, “005”, “001”, “004”, “0BC”, “004”, “002”, “001”);
@ranges = ();
# \@array and \@ranges are now normal scalar references.

Я надеюсь, вы понимаете концепцию ссылок на массивы. Если нет, прочтите perlreftut или perllol . Фактически, это не влияет на синтаксис вызова, о котором вы спрашиваете. Кстати, вы также могли написать:

$array_ref=[“0A0”, “005”, “001”, “004”, “0BC”, “004”, “002”, “001”];
$range_ref=[];

$numRanges = buildRanges(VALUES => $array_ref, REF_RANGES=> $range_ref);

Вызов функции

В Perl оператор стрелки => работает так же, как обычная запятая (с небольшим побочным эффектом, который мы обсудим чуть позже). Следующие вызовы абсолютно идентичны:

$numRanges = buildRanges(VALUES => $array_ref, REF_RANGES => $range_ref);
$numRanges = buildRanges("VALUES", $array_ref, "REF_RANGES", $range_ref);

Итак, вы просто вызываете функцию buildRanges с четырьмя аргументами: двумя постоянными строками и двумя ссылками на массив. Вы заметили, что слово VALUES было заменено на постоянную строку «VALUE»; то же самое применимо к слову REF_RANGES. Это особое правило: перед стрелкой => и внутри фигурных скобок {} простые идентификаторы автоматически преобразуются в строки. Мы снова видим это ниже. Но другие выражения, такие как $ a => $ b, остаются неизменными, здесь не происходит тихих преобразований в строки.

Вы можете спросить, почему Perl это делает? Это синтаксический сахар : оператор => не делает ничего такого, что вы не могли бы легко сделать без него. Но для опытных программистов на Perl формат KEY => $ value выглядит более понятным, чем «KEY», $ value.

Определение функции

Определение функции buildRanges может выглядеть так (и мы используем это в нашем объяснении) :

sub buidRanges { my(%info)=@_; 
  my $values    = $info{VALUES};
  my $ref_ranges= $info{REF_RANGES};
  my $special_feature = $info{SPECIAL_FEATURE}; # explained below
  if($special_feature) { ... return special_result; }
  ... process $values and $ref_ranges ... return $numRanges.
}

С вашими входными данными, каждая из следующих четырех строк имеет одинаковый эффект:

my(%info)=@_;                                          # the actual code
my(%info)=(VALUES => \@array, REF_RANGES=> \@ranges ); # what this does

my %info; $info{"VALUES"}=\@array; $info{"REF_RANGES"}=\@ranges; 
my %info; $info{ VALUES }=\@array; $info{ REF_RANGES }=\@ranges; 

Обычно входные данные преобразуются в хэш, который позволяет получить доступ к каждому аргументу. Строки констант в вызове функции становятся ключами хеширования.

Выберите одну строку, которую вы понимаете, и сравните ее с другими строками: они делают то же самое. Дополнительные объяснения см. В perldsc .

Обратите внимание, что @_ - это массив входных аргументов, в нашем случае

@_ = ( VALUES => \@array, REF_RANGES=> \@ranges); 
@_ = ("VALUES",  \@array,"REF_RANGES", \@ranges);  # without syntactic sugar

Вы могли заметить, что $ info {VALUES} эквивалентно $ info {" VALUES "} - опять же, это синтаксический сахар, как объяснено выше.

Далее в нашей гипотетической реализации мы извлекаем входные данные из хэша:

 my $values     = $info{VALUES};       # i.e:  my $value      = \@array;
 my $ref_ranges = $info{REF_RANGES};   # i.e:  my $ref_renges = \@ranges;

Теперь наша реализация функции может работать с входными данными .

Почему мы не делаем этого проще? --- Именованные аргументы

До сих пор мы могли добиться аналогичного эффекта гораздо проще: Ответ: он более гибкий и несколько более самодокументирующийся.

Чтобы прояснить суть вопроса, я добавил SPECIAL_FEATURE к нашему определению функции. Теперь функцию также можно вызвать следующим образом:

$numRanges = buildRanges(VALUES => \@array, SPECIAL_FEATURE=> "infinite ranges");

Реализованная функция может сказать, что SPECIAL_FEATURE запрошена, а REF_RANGES не предоставлены.

В некоторых высокоуровневых функциях у вас есть целый ряд дополнительных возможностей которые иногда (но не всегда) полезны, поэтому имеет смысл позволить вызывающей стороне решать, какие функции использовать, а какие нет. Здесь могут пригодиться названные аргументы.

Конечно, я не могу сказать вам, какие особенности распознаются вашим buildRanges --- вам нужно посмотреть на ее реализацию или попросить человека, который вам сказал, использовать ее. Также возможно, что по общему соглашению все высокоуровневые функции в каком-либо проекте используют этот стиль вызова, хотя некоторые из них не предоставляют особых функций.

]
28
ответ дан 18 December 2019 в 05:55
поделиться
Другие вопросы по тегам:

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