07 апреля 2020

Переменные

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

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

      Первый символ имени переменной языка Perl определяет ее тип. В языке Perl можно определить переменные трех типов: скаляр, массив и хеш-массив. Для каждого типа переменных интерпретатор создает собственное пространство имен, храня в нем идентификаторы объявленных в программе переменных заданного типа. Это позволяет создавать переменные разных типов с одинаковыми идентификаторами. В программе Perl бесконфликтно могут сосуществовать и скалярная переменная $var, и массив скаляров @var, и хеш-массив %var.

      Так как имя переменной всегда начинается с одного из символов "$", "@" или "%", то использование в качестве идентификатора "предопределенных" слов не приводит к конфликтам в процессе интерпретации программы.

      Следует отметить, что в языке Perl существует достаточно большой набор специальных встроенных переменных, которые можно использовать для получения или изменения разнообразной системной информации. Большинство из них являются скалярными переменными с "идентификатором", состоящим из одного специального символа, например, $~, $__ и т. д.

      Немного забегая вперед, скажем, что переменные используются в выражениях, которые, в свою очередь, могут являться операндами определенных в языке операций. Интерпретация операций и значений их операндов в Perl зависит от контекста, в котором они вычисляются. Существует два основных контекста: скалярный и списковый. Например, если левым операндом операции присваивания является скалярная переменная, то правый операнд вычисляется в скалярном контексте, т. е. его значением должен быть скаляр; если левый операнд массив или хеш (или фрагмент массива или хеша), то правый операнд вычисляется в списковом контексте, т. е. должен предоставить значение, являющееся списком.
Замечание
Использование конструктора массива с элементами, являющимися скалярными переменными, в качестве левого операнда операции присваивания предписывает вычислять правый операнд в списковом контексте.
     Переменные массивов и хешей, а также их конструкторы, используемые в качестве операндов операции присваивания (=), будут иметь разные значения в зависимости от используемого контекста.

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

@аггау = (0, 2, 4); # Массив скаляров баггау
# содержит три элемента: 0, 2, 4. $last = (0, 2, 4);
# Значение скалярной переменной $last равно 4.

      Переменная массива скаляров в списковом контексте возвращает список всех элементов массива, а употребленная в скалярном контексте, в отличие от своего конструктора, будет иметь значение, равное числу элементов массива:

@new_array = Sarray; # Массив @new_array
# содержит все элементы массива @аггау. $number = Sarray;
# Скалярная переменная $number
# равна 3 - числу элементов массива Sarray.

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

($а, $b = (1, 2, 3); # $а = 1, $ b = 2.
($а, $b $с) = (1, 2); tt $а= 1, $ b =2, $с = "".

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

$х = ( @а = (1, 2) ); # $х = 2.

      Хеш-переменные так же, как и массивы скаляров, ведут себя по-разному в разных контекстах. Употребленные в списковом контексте, они вычисляются в виде обычного списка, состоящего из элементов всех пар ключ/значение. Однако порядок элементов в списке может не соответствовать порядку задания пар в хеше. Это связано с тем, что внутренняя реализация хеш-массивов основана на использовании хеш-таблиц для ускорения поиска соответствия ключ/значение, поэтому при вычислении хеша в виде списка порядок следования "пар" ключ/значение и не соответствует порядку их задания, но после ключа всегда следует его значение.

%hash = ( I => I, 2 =>2, 3 => 3, 4=> 4 );
@list = %hash; # @list = (blue, 3, green, 2, red, 1, black, 4)

      В скалярном контексте вычисляемым значением хеш-массива является строка, состоящая из числа использованных участков записей (bucket) и числа выделенных участков записей, разделенных символом "/". Если присвоить скалярной переменной хеш-массив %hash предыдущего примера, то ее значением будет строка "4/8", которая говорит, что 4 из 8 выделенных участков записей хеш-таблицы используется.

      Любая переменная в Perl может находиться в состоянии: определена или не определена. Если ей присвоено какое-либо значение, то такая переменная считается определенной. Если ей не было присвоено значение до ее использования в каком-либо выражении, то такая переменная считается не определенной. Чтобы узнать, определена или нет переменная, можно воспользоваться встроенной функцией defined, которая возвращает г (Истина) в случае определенности переменной и пустую строку "", когда переменная не определена:

@т = (1,2);
defined @т; '# Возвращает 1, массив скаляров @т определен.
defined $т; # Возвращает "", переменная $т не определена.
Определенную переменную можно в любой момент сделать неопределенной, выполнив функцию undef с параметром, равным имени этой переменной:
@т = (1,2);
defined @т; # Возвращает 1, массив скаляров @т определен.
undef @m;
defined @m; tt Возвращает "", массив скаляров @т не определен.

      Если переменная сделана не определенной с помощью функции undef, TO она, естественно, теряет присвоенное ранее ей значение.

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