Для моделирования в программе внешнего мира программист создает необходимые сущности в виде
Кроме того,
В процедурных
Подобно определению sub, за которым следует имя
# определение подпрограммы:
sub say_hello { # имя подпрограммы
if ($language eq 'ru') { # тело подпрограммы
print 'Здравствуйте!';
} elsif ($language eq 'ja') {
print 'Konnichi-wa!';
} else {
print 'Hello!';
}
}
$language = 'ru'; # напечатать приветствие по-русски
say_hello; # вызов подпрограммы
Определение
В возвращает
sub dice { # бросаем игральные кости:
(int(rand 6)+1, int(rand 6)+1); # два случайных числа
}
Также в , которая завершает выполнение
sub greeting { # приветствие в зависимости от времени суток
my $hours = (localtime)[2]; # текущие часы
if ($hours >= 4 and $hours < 12) {
return 'Доброе утро';
} elsif ($hours >= 12 and $hours < 18) {
return 'Добрый день';
} elsif ($hours >= 18 and $hours < 22) {
return 'Добрый вечер';
} else {
return 'Доброй ночи';
}
}
print greeting(), '!';
Если undef - в get_file_size() возвращает
sub get_file_size { # узнать размер файла
return -s $file # вернуть размер, в т.ч. 0,
if -e $file; # если файл существует
return; # файла нет, вернуть undef
}
Использование в
Помня о том, что списки в , будет возвращен @array1 и @array2. Поэтому при необходимости вернуть несколько списочных объектов возвращаются .
Пока что в приведенных примерах @_, содержащий @_, что видно из следующего примера:
sub cube { # вычислить куб числа
return $_[0] * $_[0] * $_[0]; # умножить аргумент
}
print cube(2); # будет напечатано 8
Количество переданных @_. Для обработки списка , которая извлекает из массива
print2files($message, $file1, $file2, $file3);
sub print2files { # вывести текст в несколько файлов
my $text = shift; # 1-й параметр - текст
while (@_) {
my $file = shift; # очередное имя файла
open my $fh, ">>$file" or die;
print $fh $text;
close $fh or die;
}
}
Если переданные @_ совмещается с переданными аргументами. Это означает, что изменение элементов массива приведет к изменению значений соответствующих
sub sum2 { # вычислить сумму 2-х чисел
$_[0] = $_[1] + $_[2]; # поместить сумму в 1-й аргумент
return;
}
my $a = 1, $b = 2, $sum = 0;
sum2($sum, $a, $b);
print "$a+$b=$sum"; # будет напечатано: 1+2=3
Опыт показывает, что изменение значения
sub get_file { # считать данные из файла
my ($path, $file) = @_; # присвоить аргументы в переменные
return unless -e "$path/$file"; # авария: файла нет
open my $fh, '<', "$path/$file" or return;
my @lines = <$fh>; # прочитать все строки файла в массив
close $fh or return;
return @lines; # вернуть массив строк файла
}
my @data = get_file('/tmp', 'log.txt');
Хотя подпрограмма может изменять значения
По той же subr1(@array1, @array2), то ей будет передан @array1 и @array2. Поэтому если необходимо передать несколько списочных объектов, то передаются subr1(\@array1, \@array2).
При необходимости можно объявить подпрограмму до ее использования (
sub factorial; # вычислить факториал числа
В объявлении
yellow_submarine('We all live in a');
Кстати, в пустом
2 * 2; # результат отброшен, есть смысл, если стоит... 'Истина где-то рядом'; # ...в конце подпрограммы $x++; # используется ради побочного эффекта
Обращение к
sub_without_parameters; # вызов подпрограммы без параметров sub_with_parameters($arg1, $arg2); # и с параметрами
В современном
format_c(); # вызов подпрограммы без параметров format_text($text, $font, $size); # и с параметрами
Чтобы обращаться к пользовательской
sub circle; # объявление пользовательской функции
$area_of_circle = circle $radius; # вызов функции
sub circle { # определение пользовательской функции
return 3.141592653*$_[0]*$_[0]; # площадь круга
}
В
sub factorial ($) { # вычислить N!
my $n = shift;
return ($n <= 1) ? 1 : $n * factorial($n-1);
}
Для разработки wantarray(). Она возвращает
sub list_or_scalar {
my @result = fill_result(); # формируем результаты
if (!defined wantarray) { # пустой контекст -
return; # не возвращаем значения
} elsif (wantarray) { # списочный контекст -
return @result; # возвращаем список
} else { # скалярный контекст -
return "@result"; # возвращаем скаляр
}
}
list_or_scalar(); # вызов в пустом контексте
my @list = list_or_scalar(); # вызов в списочном контексте
my $scalar = list_or_scalar(); # вызов в скалярном контексте
В
# определение подпрограммы с 1-м параметром-скаляром
sub list_mp3 ($) {
my $path = $_[0];
# ...
}
# определение подпрограммы c 2-мя скалярными параметрами
sub translate ($$@) { # и списком скаляров
my ($from_lang, $to_lang, @words) = @_;
# ...
}
sub generate_test(); # объявление подпрограммы без параметров
Для
list_mp3 @dirs; # будет передан 1 скаляр: scalar @dirs
Перечень символов, применяемых для описания прототипов, с примерами определения
| Прототип | Требования к параметрам | Пример определения / описания | Пример вызова |
|---|---|---|---|
| () | отсутствие |
sub mytime () | mytime; |
| $ | скалярное значение | sub myrand ($) sub myrename ($$) | myrand 100; myrename $old, $new; |
| @ | sub myreverse (@) sub myjoin ($@) | myreverse $a, $b, $c; myjoin ':', $x, $y, $z; | |
| подпрограмма | sub mygrep (@) | mygrep {/ |
|
| * | элемент |
sub myopen (*$) | myopen |
| \ | взятие |
sub mykeys (\%) sub mypop (\@) sub mypush(\@@) | mykeys % |
| ; | разделитель обязательных |
sub mysubstr ($$;$) | mysubstr $str, $ |
Проверки на соответствие прототипам не выполняются, если подпрограмма вызывается устаревшим способом (с
Скалярные переменные могут хранить
$ref2max = \max; # взятие ссылки на подпрограмму
sub max { # вычисляет максимум из списка значений
my $maximum = shift;
foreach (@_) { $maximum = $_ if ($_ > $maximum); }
return $maximum;
}
print ref($ref2max); # будет выведено: CODE
Первый способ обращения к
$max_of_list = $ref2max->(@list_of_numbers);
Другая
$max_of_list = $ref2max(@list_of_numbers);
# можно окружить ссылочную переменную фигурными скобками
$max_of_list = {$ref2max}(@list_of_numbers);
Вызов
$reference_to_procedure; # с префиксом подпрограмм $reference_to_procedure->(); # с операцией разыменования
Если предполагается, что доступ к
my $ref2sum = sub { # определение анонимной подпрограммы
my $sum = 0; # вычисляет сумму списка значений
$sum += $_ foreach (@_);
return $sum;
}; # конец операции присваивания переменной $ref2sum
print $ref2sum->(1..5), " \n";
my @refs = ($ref2read, $ref2calc, $ref2format);
for (my $i = 0; $i < @refs; $i++) {
@data = $refs[$i]->(@data); # обработать данные
}
В других случаях
my %refs2subs = ('SUM' => $ref2sum, 'MAX' => $ref2max);
print $refs2subs{'SUM'}->(1..3), " \n";
В my(), как это уже делалось в приводимых ранее примерах. Когда при помощи my объявляется несколько
my ($var1, $var2, $var3) = (1, 2, 3); # правильно # запись my ($var1=1, $var2=2, $var3=3) ошибочна my $var4 = 4, $var5 = 5; # $var5 - глобальная, а не my
Чтобы проследить, как изменяются
use strict;
my $var = 'm'; # лексическая $var в main
print "1(main)='$var'\n"; # выведет: 1(main)='m'
sub1();
print "7(main):'$var'\n"; # выведет: 7(main):'z'
sub sub1 {
print "2(sub1)='$var'";
$var = 's'; # изменяется $var из main!
print "-->'$var'\n"; # выведет: 2(sub1)='m'-->'s'
my $var = '1'; # изменена $var из sub1
print "3(sub1)='$var'\n"; # выведет: 3(sub1)='1'
sub2();
# снова видима $var из sub1
print "6(sub1):'$var'\n"; # выведет: 6(sub1):'1'
}
sub sub2 { # снова видима $var из main
print "4(sub2):'$var'";
$var = 'z'; # изменяется $var из main!!
print "-->'$var'\n"; # выведет: 4(sub2):'s'-->'z'
my $var = '2'; # изменена $var1 из sub2
print "5(sub2)='$var'\n"; # выведет: 5(sub2)='2'
}
Обратите внимание, что лексическая переменная $, объявленная в главной программе, видима в обеих sub1 и sub2, поскольку они статически объявлены в рамках той же программы. Но при выполнении программы в sub2 не видима переменная $, объявленная в sub1. Из приведенного примера видно, что после объявления в my(), изменения этих use . Другая разновидность лексических our, будет рассмотрена в следующей лекции.
В , также влияющая на , потому что ее основное назначение - скрыть текущее значение или программном файле. Это значит, что после выполнения переменные иногда говорят, что она описывает , должны заключаться в круглые скобки, как показано ниже:
local $_; # временно скрыть значение буферной переменной local ($global1, $equant) = (1, 2); # правильно
Посмотрите, как изменится результат, если переписать предыдущий пример с использованием вместо my в sub1:
$var = 'm'; # ГЛОБАЛЬНУЮ $var можно скрыть через local
print "1[main]='$var'\n"; # выведет: 1[main]='m'
sub1();
print "7[main]:'$var'\n"; # выведет: 7[main]:'s'
sub sub1 {
print "2[sub1]='$var'";
$var = 's'; # изменена $var из main!
print "-->'$var'\n"; # выведет: 2[sub1]='m'-->'s'
local $var = '1'; # значение ГЛОБАЛЬНОЙ $var скрывается
print "3[sub1]#'$var'\n"; # выведет: 3[sub1]#'1'
sub2();
print "6[sub1]:'$var'\n"; # выведет: 6[sub1]:'z'
}
sub sub2 { # видна ГЛОБАЛЬНАЯ $var из sub1
print "4[sub2]:'$var'";
$var = 'z'; # изменена $var из sub1!
print "-->'$var'\n"; # выведет: 4[sub2]:'1'-->'z'
my $var = '2'; # изменена $var из sub2
print "5[sub2]='$var'\n"; # выведет: 5[sub2]='2'
}
Сравнивая эту программу с предыдущим примером, можно отметить следующие отличия.
$var в главной программе пришлось сделать глобальной, так как local не может скрывать лексические переменные.local распространяется до конца sub1, а также на вызываемую подпрограмму sub2.sub1 действие local заканчивается и восстанавливается значение, которое содержала глобальная переменная $var до применения к ней local .В современных программах в основном используют функцию my для задания переменным лексической в
С помощью ссылок,
my $ref; # переменная для хранения ссылки
{ # в блоке создается
my $lex_var = 'Суслик'; # переменная $lex_var
$ref = \$lex_var; # в $ref помещена
} # ссылка на переменную
# $lex_var освобождается при выходе из блока
print "Ты суслика видишь? И я не вижу. А он есть: ";
print ${$ref}; # объект ссылки доступен через $ref
Подобным образом можно хранить ссылку на анонимную подпрограмму, из которой будут доступны динамически созданные лексические переменные. Такая подпрограмма, вызванная по ссылке, будет иметь доступ к
my $ref; # переменная для хранения ссылки
{ # в блоке создается
my $lex_var = 'Верблюд'; # переменная $lex_var
$ref = sub { return $lex_var }; # в $ref помещена
} # ссылка на подпрограмму
# $lex_var освобождается при выходе из блока
print $ref; # объект возвращается подпрограммой по $ref
Замыкания можно создавать динамически при выполнении программы. Приведем пример функции, которая при каждом вызове создает замыкание и возвращает ссылку на него. При этом каждый раз создается новый экземпляр лексической
sub make_closure { # функция создания замыканий:
my ($animal) = @_; # В лексической переменной
# сохраняется аргумент функции
my $ref2closure = sub { # и ссылка на
# анонимную подпрограмму,
return $animal; # которая имеет доступ
}; # к лексической переменной.
return $ref2closure; # возвращает ссылку на подпрограмму
}
# создаем 2 замыкания, сохраняя в них разные значения:
my $camel1 = make_closure('дромадер'); # одногорбый верблюд
my $camel2 = make_closure('бактриан'); # двугорбый верблюд
print $camel1, ' ', $camel2->(); # доступ по ссылкам
В этой лекции изложены основные сведения о
perldoc perlsub
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.