Возвращаемым значением операции присваивания в Perl является, в отличие от других языков
программирования, в том числе языка С, не присваиваемое значение правого операнда, а ссылка на
область памяти, определяемую правильным l-значением левого операнда. В приведенном нами примере —
переменной $а. Проще говоря, можно представить себе возвращаемое значение операции простого
присваивания как просто переменную, определяемую левым операндом операции присваивания. А коль скоро
возвращаемое значение является правильным l-значением, то его снова можно использовать в качестве
операнда операции, которой требуется правильное l-значение. Таким образом, в языке Perl следующее выражение
($temp = $а) =~ s/<(.+?)>/<\L$1\U>/g
является синтаксически правильным. Смысл использования подобного выражения в том, что мы применяем
результат замены строкового содержимого переменной $а не к ней самой, а к ее копии, сохраненной в
переменной $temp.
Синтаксические правила языка Perl позволяют осуществлять присваивание одного и того же значения
нескольким переменным в одном выражении:
$var1 = $var2 = $var[0] = 34;
Подобное действие возможно, так как операция простого присваивания обладает свойством сочетаемости
справа налево, то есть если в выражении встречается несколько операций присваивания, то они выполняются
справа налево. Поэтому в приведенном операторе сначала первому элементу массива скаляров @var будет
присвоено значение 34 и возвратится ссылка на область памяти его размещения. В следующей операции
присваивания скалярной переменной $var2 будет присвоено значение, содержащееся в первом элементе
массива @var1 (оно равно 34), и возвращена ссылка на область памяти расположения переменной $var2.
После выполнения последней операции присваивания скалярная переменная $var1 будет иметь такое же
значение, что и переменная $var2, и результатом вычисления всего выражения будет ссылка на область
памяти, выделенной под переменную $var1, то есть сама переменная $var1.
Операции сложного присваивания
Очень часто при реализации вычислительных алгоритмов приходится использовать значения некоторой
переменной и результат присваивать этой же переменной. Например, увеличить на 2 значение переменной $а
и результат присвоить этой же переменной $а. Это действие можно реализовать следующей операцией простого
присваивания:
$а = $а + 2;
Однако язык Perl предлагает более эффективный способ решения подобных задач, предоставляя в
распоряжение программиста бинарную операцию сложного присваивания (+=), которая прибавляет к значению
левого операнда, представляющего правильное l-значение, значение правого операнда, и результат
присваивает переменной, представленной левым операндом. Таким образом, предыдущий оператор простого
присваивания эквивалентен следующему оператору сложного присваивания:
$а += 2; # Результат: $а = $a + 2
Единственное отличие заключается в том, что его реализация эффективнее реализации простого
присваивания, так как в составном операторе присваивания переменная $а вычисляется один раз, а в
простом ее приходится вычислять дважды. (Под вычислением переменной понимается вычисление адреса
представляемой ею области памяти и извлечение значения, хранящегося в этой области памяти.)
Для всех бинарных операций языка Perl существуют соответствующие операции сложного присваивания.
Все они, вместе с примерами их использования, собраны в табл. 4.8.
Таблица 4.8. Операции сложного присваивания
Операция |
Пример |
Эквивалентная операция простого присваивания |
**= |
$а **= 2; |
$а = $а ** 2; |
+= |
$а += 2; |
$а = $а + 2; |
-= |
$а -= 2; |
$а = $а - 2; |
.= |
$а .= "2"; |
$а = $а."2"; |
*= |
$а *= 2; |
$а = $а * 2; |
/= |
$а /= 2; |
$а = $а / 2; |
%= |
$а %= 2; |
$а = $a % 2; |
x= |
$a x= 2; |
$а = $а х 2; |
&= |
$а &= $b; |
$а = $а & $b; |
|= |
$а |= $b; |
$а = $а | $b; |
^= |
$а ^= $b; |
$а = $а ^ $b; |
<<= |
$а <<= 2; |
$а = $а << 2; |
>>= |
$а >>= 2; |
$а = $а >> 2; |
&&= |
$а &&= $b>0; |
$a = $a && ($b>0); |
||= |
$а ||= $b == 0; |
$а = $а || ($b==0); |
Возвращаемым значением каждой из операций сложного присваивания, как и в случае простого
присваивания, также является ссылка на область памяти, определяемую левым операндом (правильное l-значение).
Поэтому эти операции можно использовать в любом операнде других операций присваивания:
$b = 1;
$а = $b += 3; — результат: $а = $b = 4;
$а += $b += 3; - результат = $а=$b+3;
(($а += 2) **= 2) -= 1; - результат $a = ($а + 2) ** 2 - 1
При использовании операции присваивания (простой или сложной) в качестве левого операнда другой
операции присваивания обязательно ее заключение в круглые скобки. Иначе может сгенерироваться
синтаксическая ошибка или выражение будет интерпретировано не так, как задумывалось. При наличии
нескольких операций присваивания в одном выражении без скобок следует помнить, что интерпретатор perl
начинает его разбор справа. Например, если последнее выражение из приведенного выше примера записать
без скобок: $а += 2 **= 2 -= 1, то при его синтаксическом анализе интерпретатор сначала выделит операцию
присваивания 2 -= 1 и тут же сообщит об ошибке, так как ее левый операнд не является правильным l-значением.
ВНИМАНИЕ. Операции сложного присваивания в списковом контексте не используются, поэтому операция
@array+=4 приведет к синтаксической ошибке во время компиляции.