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

Переменные, объявленные с ключевым словом my, являются приватными для пользовательской функции; при каждом последующем вызове они определяются заново. С ключевым словом state область видимости приватных переменных поQпрежнему ограничивается пользовательской функцией, но Perl сохраняет их значения между вызовами. Вернемся к первому примеру этой главы – в нем определялась функция marine, которая увеличивала значение переменной:

sub marine {
$n += 1; # Глобальная переменная $n
print "Hello, sailor number $n!\n";
}

Но вы уже знаете о директиве use strict, можете включить ее в программу… и понять, что теперь наше использование глобальной переменной $n стало невозможным. Переменную $n нельзя объявить лексической с ключевым словом my, потому что она не будет сохранять свое значение между вызовами. Проблема решается объявлением переменной с ключевым словом state. Такие переменные сохраняют свое значение между вызовами функции, а область их видимости ограничивается пользовательской функцией:

use 5.010;
sub marine {
state $n = 0; # private, persistent variable $n
$n += 1;
print "Hello, sailor number $n!\n";
}

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


При первом вызове функции Perl объявляет и инициализирует $n, а при всех последующих вызовах объявление игнорируется. Между вызовами Perl сохраняет текущее значение $n.

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

use 5.010;
running_sum( 5, 6 );
running_sum( 1..3 );
running_sum( 4 );
sub running_sum {
state $sum = 0;
state @numbers;
foreach my $number ( @_ ) {
push @numbers, $number;
$sum += $number;
}
say "The sum of (@numbers) is $sum";
}

При каждом вызове функция выводит новую сумму, прибавляя новые аргументы ко всем аргументам от предыдущих вызовов:

The sum of (5 6) is 11
The sum of (5 6 1 2 3) is 17
The sum of (5 6 1 2 3 4) is 21

Впрочем, для массивов и хешей устанавливается небольшое ограничение: в Perl 5.10 запрещена их инициализация в списочном контексте:

state @array = qw(a b c); # Ошибка!

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

Initialization of state variables in list context currently forbidden ...

Оцените статью: (0 голосов)
0 5 0

Статьи из раздела Perl на эту тему:
Аргументы
Возвращаемые значения
Вызов пользовательской функции
Вызов функции без &
Директива use strict

Вернуться в раздел: Perl / 3. Пользовательские функции