Выражения
Контекст
Наш разговор о выражениях Perl был бы не полным, если бы обошли стороной такое понятие, как контекст. Каждая операция и каждый терм вычисляются в определенном контексте, который определяет поведение операции и интерпретацию возвращаемого ею значения. Существует два основных контекста: скалярный и списковый. В главе 3 мы уже немного познакомились с ними, когда определяли поведение конструктора массива и переменной массива в правой части оператора присваивания. Их можно "определить" так: если для выполнения операции требуются скалярные данные, то действует скалярный контекст, если необходимы массивы скаляров, то программа находится в списковом контексте.
Например, если левый операнд операции присваивания, скалярная переменная, то действует скалярный контекст, если же в левой части задан массив, хеш или фрагмент массива или хеша, то вычисления в правой части осуществляются в списковом контексте. Присваивание списку скалярных переменных также инициирует списковый контекст для вычислений, осуществляемых в правой части операции.
Некоторые операции Perl распознают контекст, в котором они вычисляются, и возвращают список в списковом контексте и скалярное значение в скалярном контексте. Обладает ли операция подобным поведением, можно всегда выяснить из ее описания в документации. Например, можно рассматривать префикс @ перед идентификатором как унарную операцию объявления массива скаляров, распознающую контекст, в котором она вычисляется. В списковом контексте она возвращает список элементов массива, а в скалярном – число элементов массива.
Некоторые операции поддерживают списковый контекст для своих операндов (в основном это списковые операции), и это также можно узнать из описания их синтаксиса, в котором присутствует СПИСОК (LIST). Например, известная уже нам операция создания фрагмента массива splice поддерживает списковый контекст для своих параметров, поэтому ее можно вызывать вот таким образом:
@s = (1, 2); splice @m, @s; # Эквивалентно: splice @m, <strong>I</strong>, 2;
Скалярный контекст можно подразделить на числовой, строковый и безразличный. Если скалярный и списковый контекст некоторыми операциями распознается, то ни одна операция не может определить, вычисляется ли она в числовом или строковом скалярном контексте. Perl просто при необходимости преобразует возвращаемые операцией числа в строки и наоборот. В некоторых случаях вообще не важно, возвращается ли операцией число или строка. Подобное, например, происходит при присваивании переменной какого-либо значения. Переменная просто принимает подтип присваиваемого значения. Такой контекст называется безразличным.
В языке существует булевый контекст – специальный тип скалярного контекста, в котором вычисленное значение выражения трактуется только как Истина или Ложь. Как уже отмечалось ранее, в Perl нет специального булева типа данных. Здесь любая скалярная величина трактуется как Истина, если только она не равна пустой строке "" или числу о. (Строковый эквивалент ложности – строка из одного нуля "о"; любая другая строка, эквивалентная нулевому значению, считается в булевом контексте истинной, например, "оо" или "о.о".)
Другим специфическим типом скалярного контекста является void-контекст. Он не только не заботится о подтипе возвращаемого значения – скалярный или числовой, но ему и не надо никакого возвращаемого значения. Этот контекст возникает при вычислении выражения без побочного эффекта, т. е. когда не изменяется никакая переменная программы. Например, следующие выражения вычисляются в void-контексте:
$n; "текст";
Этот контекст можно "обнаружить", если установить ключ – w компилятора Perl. Тогда можно получить предупреждающее сообщение следующего типа:
Useless use of a variable in void context at D:\P\EX.PL line 3. (Бесполезное использование переменной в, void-контексте в строке 3 программы D:\P\EX.PL)
Завершит наш рассказ о контексте подстановочный контекст (interpolative context), в котором вычисляются операции заключения в кавычки (кроме заключения в одинарные кавычки). В этом контексте вместо любой переменной, заданной в строке, в нее подставляется значение этой переменной, а также интерпретируются управляющие последовательности.
В этой главе мы изучили практически все скалярные операции языка Perl, чуть-чуть коснулись операций сопоставления по образцу, создания ссылок и операций ввода\вывода, познакомились с основами работы со списковыми и унарными именованными операциями. Узнали, что такое выражение, а также в каком порядке вычисляются в нем операции на основе их приоритета и сочетаемости. Научились выделять термы в выражениях и выяснили, в каких контекстах могут вычисляться выражения.