4.6. Операции присваивания
Глава 4 Операции и выражения
🕛 02.11.2006, 15:41
Присваивание переменной какого-либо значения, определенного литералом, или присваивание одной переменной значения другой переменной является наиболее часто выполняемым действием в программе, написанной на любом языке программирования. В одних языках это действие определяется с помощью оператора, а в других - с помощью операции. Отличие заключается в том, что в языках, где присваивание является операцией, оно может использоваться в выражениях как его составная часть, так как любая операция вычисляет определенное значение, тогда как оператор всего лишь производит действие. В языке Perl присваивание является операцией, которая возвращает правильное lvalue. Что это такое, мы разъясним буквально в следующих абзацах.Операция присваивания =, с которой читатель уже немного знаком, является бинарной операцией, правый операнд которой может быть любым правильным выражением, тогда как левый операнд должен определять область памяти, куда операция присваивания помещает вычисленное значение правого операнда. В этом случае и говорят, что левый операнд должен быть правильным lvalue (от английского left value - левое значение). А что мы можем использовать в программе для обозначения области памяти? Правильно, переменные. Следовательно, в качестве левого операнда операции присваивания можно использовать переменную любого типа или элемент любого массива. (В языке Perl существуют и другие объекты, которые можно использовать в качестве левого операнда операции присваивания, но об этом в свое время.) Следующая операция простого присваивания $а = $Ь+3;
вычислит значение правого операнда и присвоит его переменной $а, т.е. сохранит в области памяти, выделенной для переменной $а. Возвращаемым значением этой операции будет адрес области памяти переменной $а (правильное lvalue), или говоря проще, имя скалярной переменной $а, которое снова можно использовать в качестве левого операнда операции присваивания. Таким образом, в языке Perl следующая операция присваивания
($а = $Ь) = 3;
является синтаксически правильной и в результате ее вычисления переменной $а будет присвоено значение з, так результатом вычисления операции присваивания $а = $ь будет присвоение переменной $а значения переменной $ь, а возвращаемым значением можно считать переменную $а, которой в следующей операции присваивается значение з. Читатель спросит: "А зачем городить такие сложности, если тот же самый результат можно получить простой операцией присваивания $а = з?". Действительно, замечание справедливое. Но на этом примере мы показали, как можно использовать операцию присваивания в качестве правильного lvalue. Более интересные примеры мы покажем, когда определим составные операции присваивания, заимствованные из языка С.
Синтаксические правила языка Perl позволяют осуществлять присваивание одного и того же значения нескольким переменным в одном выражении:
$varl = $var2 = $varl[0] =34;
Очень часто при реализации вычислительных алгоритмов приходится осуществлять разнообразные вычисления с использованием значения некоторой переменной и результат присваивать этой же переменной. Например, увеличить на з значение переменной $а и результат присвоить этой же переменной $а. Это действие можно реализовать следующей операцией присваивания:
$а = $а+3;
Однако, язык Perl предлагает более эффективный способ решения подобных проблем, предоставляя в распоряжение программиста бинарную операцию составного присваивания +=, которая прибавляет к значению левого операнда, представляющего правильное lvalue, значение правого операнда и результат присваивает переменной, представленной левым операндом. Таким образом, оператор составного присваивания
$а += 3; I Результат: $а = $а+3
эквивалентен предыдущему оператору простого присваивания. Единственное отличие заключается в том, что его реализация эффективнее реализации простого присваивания, так как в составном операторе присваивания переменная $а вычисляется один раз, тогда как в простом ее приходится вычислять дважды. (Под вычислением переменной понимается вычисление адреса представляемой ею области памяти и извлечение значения, хранящегося в этой области памяти.)
Для всех бинарных операций языка Perl существуют соответствующие составные операции присваивания. Все они, вместе с примерами их использования, собраны в табл. 4.2.
Таблица 4.2. Составные операции присваивания
Операция Пример Эквивалент с операцией простого присваивания
**= $а **= 3; $а = $а ** 3;
+= $а += 3; $а = $а + 3;
-= $а -= 3; $а = $а - 3;
.= $а .= "а"; $а = $а . "а";
*= $а *= 3; $а = $а * 3;
/= $а /= 3; $а = $а / 3;
%= $а %= 3; $а = $а % 3;
х= $а х= 3; $а = $а х 3;
&= $а &= $b; $а = $а & $b;
|= $а |= 3; $а = $а | 3;
^= $а ^= 3; $а = $а ^ 3;
«= $а «= 3; $а = $а « 3;
»= $а »= 3; $а = $а » 3;
&&= $а &&= $b > 1; $а = $а && $b > 1;
||= $а ||= $b == 0; $а = $а || $b == 0;
Возвращаемым значением каждой из составных операций присваивания, как и в случае простого присваивания, является переменная левого Операнда (правильное lvalue), поэтому их можно использовать в любом операнде других операций присваивания (пример 4.11).
$Ь = 1;
$а = ($Ь +=3); # Результат: $а = $Ь = 4
$а += ($Ь += 3); # Результат: $а = $а+$Ь+3
( ($а += 2) **= 2) -= 1; # Результат: $а = ($а+2)**2-1
Замечание При использовании операции присваивания (простой или составной) в качестве левого операнда другой операции присваивания обязательно ее заключение в круглые скобки. Иначе может сгенерироваться синтаксическая ошибка, или выражение будет интерпретировано не так, как задумывалось. При наличии нескольких операций присваивания в одном выражении без скобок интерпретатор peri начинает его разбор справа. Например, если последнее выражение примера 4.11 записать без скобок
$а += 2 **= 2 -= 1;
то при его синтаксическом анализе интерпретатор сначала выделит операцию присваивания
2 -= 1;
и сообщит об ошибке, так как ее синтаксис ошибочен (левый операнд не является переменной или элементом массива).