Доступ к аргументам подпрограммы

Проблема

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

Решение

Все значения, переданные функции в качестве аргументов, хранятся в специальном массиве @_. Следовательно, первый аргумент хранится в элементе $_[0], второй — в $_[1] и т. д. Общее число аргументов равно sсаlаr(@_). Например:
sub hypotenuse {
  return sqrt( ($_[0] ** 2) + ($_[1] ** 2) );
}
$diag = hypotenuse(3.4);         # $diag = 5
В начале подпрограммы аргументы почти всегда копируются в именованные закрытые переменные для удобства и повышения надежности:
sub hypotenuse {
  my ($side1, $side2) = @_;
  return sqrt( ($side1 ** 2) + ($side2 ** 2) );
}

Комментарий

Говорят, в программировании есть всего три удобных числа: ноль, единица «сколько угодно». Механизм работы с подпрограммами Perl разрабатывался для упрощения написания функций со сколь угодно большим (или малым) числом параметров и возвращаемых значений. Все входные параметры хранятся в виде дельных скалярных значений в специальном массиве @_, который автоматически становится локальным для каждой функции. Для возвращения значений из подпрограмм следует использовать команду return с аргументом. Если она отсутствует, возвращаемое значение представляет собой результат последнего вычисленного выражения.
Приведем несколько примеров вызова функции hypotenuse, определенной в решении:
print hypotenuse(3, 4), "\n";   # Выводит 5
@а = (3, 4);
print hypotenuse(@a), "\n";     # Выводит 5
Если взглянуть на аргументы, использованные во втором вызове hypotenuse, может показаться, что мы передали лишь один аргумент — массив @а. Но это не так — элементы @а копируются в массив @_ по отдельности. Аналогично, при вызове функции с аргументами (@а, @b) мы передаем ей все аргументы из обоих массивов. При этом используется тот же принцип, что и при сглаживании списков:
@both = (@men, @women);
Скалярные величины в @_ представляют собой неявные синонимы для передаваемых значений, а не их копии. Таким образом, модификация элементов @_ в подпрограмме приведет к изменению значений на вызывающей стороне. Это тяжкое наследие пришло из тех времен, когда в Perl еще не было нормальных ссылок.
Итак, функцию можно записать так, чтобы она не изменяла свои аргументы — для этого следует скопировать их в закрытые переменные
@nums = (1.4, 3.5, 6.7);
@ints = int_all(@nums);   # @nums не изменяется
sub int_all {
  my @retlist = @_;       # Сделать копию для return
  for my $n (@retlist) { $n = int($n) }
  return @retlist;
}
Впрочем, функция также может изменять значения переменных вызывающей стороны:
@nums = (1.4, 3.5, 6.7);
trunc_em(@nums);         # @nums = (1,3,6)
sub trunc_em {
  for (@_) { $_ = int($_) }  # Округлить каждый аргумент
}
Таким функциям не следует передавать константы — например, trunc_em(1.4, 3.5, 6.7). Если попытаться это сделать, будет возбуждено исключение Modification of a read-only value attempted at... («Попытка модифицировать величину, доступную только для чтения»).
Встроенные функции chop и chomp работают именно так — они модифицируют переменные вызывающей стороны и возвращают удаленный символ(-ы). Многие привыкают к тому, что функции возвращают измененные значения, и часто пишут в программах следующее:
$linе = chomp(<>);      # НЕВЕРНО
пока не поймут, что происходит в действительности. Учитывая широкие возможности для ошибок, перед модификацией @_ в подпрограмме стоит дважды подумать.

См. также




2013-09-10 17:05:19

Proverte kod v komentariyah gde pro list tam oshibki detskie




Оставить комментарий:
Ваше Имя:
Email:
Антибот: *  
Ваш комментарий: