Perl: подпрограммы (функции)

Подпрограммы Perl — это определяемые пользователем функции.

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

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

Подпрограммы Perl помогают модуляризировать программы, делая код более понятным, удобным для сопровождения и повторного использования.

Подпрограммы Perl могут располагаться в любом месте программы, используя следующий синтаксис:

sub subroutine{
   statements;
}

Синтаксис вызова подпрограммы:

subroutine( 参数列表 );

В версиях ниже Perl 5.0 способ вызова подпрограммы следующий:

&subroutine( 参数列表 );

В новых версиях, хотя такой способ вызова всё ещё поддерживается, он не рекомендуется.

Теперь давайте рассмотрим простой пример:

Пример

#!/usr/bin/perl # Определение функции sub Hello{ print "Hello, World!\n"; } # Вызов функции Hello();

Выполнение вышеуказанной программы дает следующий вывод:

Hello, World!

Передача параметров подпрограммам

Как и в других языках программирования, подпрограммы Perl могут принимать несколько параметров. Параметры подпрограммы обозначаются специальным массивом @_.

Следовательно, первый параметр подпрограммы — $_

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

Пример

#!/usr/bin/perl # Определение функции для вычисления среднего sub Average{ # Получить все переданные параметры $n = scalar(@_); $sum = 0; foreach $item (@_){ $sum += $item; } $average = $sum /$n; print 'Переданные параметры: ',"@_\n"; # Вывести весь массив print "Значение первого параметра: $_

Выполнение вышеуказанной программы дает следующий вывод:

传入的参数为 : 10 20 30
第一个参数值为 : 10
传入参数的平均值为 : 20

Пользователи могут изменять значения соответствующих фактических параметров, изменяя значения в массиве @_.

Передача списков в подпрограммы

Поскольку переменная @_ является массивом, она может передавать списки в подпрограммы.

Однако, если нам нужно передать скалярные параметры и параметры-массивы, список следует размещать последним, как показано ниже:

Пример

#!/usr/bin/perl # Определить функцию sub PrintList{ my @list = @_; print "Список: @list\n"; } $a = 10; @b = (1, 2, 3, 4); # Параметр списка PrintList($a, @b);

Приведённая выше программа объединяет скаляр и массив, и вывод будет следующим:

列表为 : 10 1 2 3 4

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

Передача хешей в подпрограммы

Когда хеш передаётся в подпрограмму, он копируется в @_, а хеш разворачивается в список пар ключ/значение.

Пример

#!/usr/bin/perl # Определение метода sub PrintHash{ my (%hash) = @_; foreach my $key ( keys %hash ){ my $value = $hash{$key}; print "$key : $value\n"; } } %hash = ('name' => 'example', 'age' => 3); # Передать хеш PrintHash(%hash);

Выполнение вышеуказанной программы дает следующий вывод:

age : 3
name : example

Возвращаемые значения подпрограмм

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

Если оператор return не используется, последний выполненный оператор в подпрограмме рассматривается как возвращаемое значение.

Пример

#!/usr/bin/perl # Определение метода sub add_a_b{ # Без использования return $_[0]+$_[1]; # Использование return # return $_[0]+$_[1]; } print add_a_b(1, 2)

Выполнение вышеуказанной программы дает следующий вывод:

3

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

Пример

sub return_multiple_data {
    my @array1 = (1, 2, 3);
    my @array2 = ('a', 'b', 'c');
    my %hash1 = ('key1' => 'value1', 'key2' => 'value2');
    my %hash2 = ('foo' => 'bar', 'baz' => 'qux');
   
    return (\@array1, \@array2, \%hash1, \%hash2);
}

my ($array_ref1, $array_ref2, $hash_ref1, $hash_ref2) = return_multiple_data();

# Используйте ссылки для доступа к возвращённым данным
print "Массив 1: @{$array_ref1}\n";
print "Массив 2: @{$array_ref2}\n";
print "Хэш 1: " . join(", ", %{$hash_ref1}) . "\n";
print "Хэш 2: " . join(", ", %{$hash_ref2}) . "\n";

В приведённом выше коде подпрограмма return_multiple_data возвращает ссылки на четыре структуры данных.

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

Вывод:

Array 1: 1 2 3
Array 2: a b c
Hash 1: key1, value1, key2, value2
Hash 2: foo, bar, baz, qux

Приватные переменные в подпрограммах

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

Если нам нужно задать приватные переменные, мы можем использоватьmyоператор `my` для установки.

myОператор `my` используется для создания переменных с лексической областью видимости.myПеременные, созданные с помощью `my`, существуют от точки объявления до конца охватывающей области видимости.

Охватывающая область видимости может быть областью внутри пары фигурных скобок, файлом или строкой if, while, for, foreach или eval.

В следующем примере показано, как объявить одну или несколько приватных переменных:

sub somefunc {
   my $variable; # $variable 在方法 somefunc() 外不可见
   my ($another, @an_array, %a_hash); #  同时声明多个变量
}

Пример

#!/usr/bin/perl # Глобальная переменная $string = "Hello, World!"; # Определение функции sub PrintHello{ # Приватная переменная функции PrintHello my $string; $string = "Привет, Example!"; print "Строка внутри функции:$string\n"; } # Вызов функции PrintHello(); print "Строка вне функции:$string\n";

Выполнение вышеуказанной программы дает следующий вывод:

函数内字符串:Hello, Example!
函数外字符串:Hello, World!

Временное присваивание переменных

Мы можем использовать local, чтобы задать временное значение для глобальной переменной, а исходное значение восстанавливается после выхода из области видимости.

Переменные, определённые с помощью local, не существуют в основной программе, но существуют в подпрограмме и в подпрограммах, вызываемых этой подпрограммой. Им можно присвоить значение при определении, например:

Пример

#!/usr/bin/perl # Глобальная переменная $string = "Hello, World!"; sub PrintExample{ # Приватная переменная функции PrintHello local $string; $string = "Привет, Example!"; # Подпрограмма, вызываемая подпрограммой PrintMe(); print "Значение строки внутри функции PrintExample:$string\n"; } sub PrintMe{ print "Значение строки внутри функции PrintMe:$string\n"; } sub PrintHello{ print "Значение строки внутри функции PrintHello:$string\n"; } # Вызов функции PrintExample(); PrintHello(); print "Строковое значение вне функции:$string\n";

Выполнение вышеуказанной программы дает следующий вывод:

PrintMe 函数内字符串值:Hello, Example!
PrintExample 函数内字符串值:Hello, Example!
PrintHello 函数内字符串值:Hello, World!
函数外部字符串值:Hello, World!

Статические переменные

Оператор state действует как модификатор static в C; ключевое слово state делает локальные переменные постоянными.

state также является лексической переменной, поэтому он допустим только в лексической области видимости, где определена переменная. Например:

Пример

#!/usr/bin/perl use feature 'state'; sub PrintCount{ state $count = 0; # Инициализировать переменную print "Значение счётчика:$count\n"; $count++; } for (1..5){ PrintCount(); }

Выполнение вышеуказанной программы дает следующий вывод:

counter 值为:0
counter 值为:1
counter 值为:2
counter 值为:3
counter 值为:4

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

Примечание 2: state был введён начиная с Perl 5.9.4, поэтому перед использованием необходимо добавить `use`.

Примечание 3: state может объявлять скаляры, массивы и хеши. Однако при объявлении массивов и хешей их нельзя инициализировать (по крайней мере, это не поддерживается в Perl 5.14).


Контекст вызова подпрограммы

Во время вызова подпрограммы возвращаются различные типы значений в зависимости от контекста. Например, подпрограмма localtime(), приведённая ниже, возвращает строку в скалярном контексте и список в списковом контексте:

Пример

#!/usr/bin/perl # Скалярный контекст my $datestring = localtime( time ); print $datestring; print "\n"; # Списковый контекст # Значение $year — это счёт, начинающийся с 1900 года как базового года ($sec,$min,$hour,$mday,$mon, $year,$wday,$yday,$isdst) = localtime(time); printf("%d-%d-%d %d:%d:%d",$year+1900,$mon+1,$mday,$hour,$min,$sec); print "\n";

Выполнение вышеуказанной программы дает следующий вывод:

Sun Jun 12 15:58:09 2016
2106-6-12 15:58:9
Другие расширения