fenom/docs/ru/operators.md
2020-04-27 10:10:55 +04:00

310 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Операторы
=========
### Арифметические операторы
Все же помнят арифметику?
* `-$a` - отрицание знака, смена знака `$a`.
* `$a + $b` - сложение, сумма `$a` и `$b`.
* `$a - $b` - вычитание, разность `$a` и `$b`.
* `$a * $b` - умножение, произведение `$a` и `$b`.
* `$a / $b` - деление, частное от деления `$a` на `$b`.
* `$a % $b` - деление по модулю, целочисленный остаток от деления `$a` на `$b`.
```smarty
{$a + $b * $c/$d - $e*5 + 1e3}
```
### Логические операторы
* `$a || $b` - логичесое ИЛИ, TRUE если или `$a`, или `$b` TRUE.
* `$a && $b` - лигическое И, TRUE если и `$a`, и `$b` TRUE.
* `!$a` - отрицание, TRUE если `$a` не TRUE.
* `$a or $b` - логическое ИЛИ, TRUE если или `$a`, или `$b` TRUE.
* `$a and $b` - логическое И, TRUE если и `$a`, и `$b` TRUE.
* `$a xor $b` - исключающее или, TRUE если `$a`, или `$b` TRUE, но не оба.
```smarty
{if $b && $c} ... {/if}
```
Смысл двух разных вариантов для операторов `and` и `or` в том, что они работают с различными приоритетами.
### Операторы сравнения
Операторы сравнения, как это видно из их названия, позволяют сравнивать между собой два значения.
* `$a < $b` - меньше, TRUE если `$a` строго меньше `$b`.
* `$a > $b` - больше, TRUE если `$a` строго больше `$b`.
* `$a <= $b` - меньше или равно, TRUE если `$a` меньше или равно `$b`.
* `$a >= $b` - больше или равно, TRUE если `$a` больше или равно `$b`.
* `$a == $b` - равно, TRUE если `$a` равно `$b` после преобразования типов.
* `$a === $b` - тождественно равно, TRUE если `$a` равно `$b` и имеет тот же тип.
* `$a !== $b` - тождественно не равно, TRUE если `$a` не равно `$b` или они разных типов.
* `$a != $b` - не равно, TRUE если `$a` не равно `$b` после преобразования типов.
* `$a <> $b` - не равно, TRUE если `$a` не равно `$b` после преобразования типов.
```smarty
{if $b >= 5} ... {/if}
```
В случае, если вы сравниваете число со строкой или две строки, содержащие числа, каждая строка будет преобразована в число, и сравниваться они будут как числа.
```smarty
{if 0 == "a"} {* 0 == 0 -> true *} {/if}
{if "1" == "01"} {* 1 == 1 -> true *} {/if}
{if "10" == "1e1"} {* 10 == 10 -> true *} {/if}
{if 100 == "1e2"} {* 100 == 100 -> true *} {/if}
```
Преобразование типов не происходит при использовании `===` или `!==` так как в этом случае кроме самих значений сравниваются еще и типы.
**Таблица сравнения различных типов:**
| Тип операнда 1 | Тип операнда 2 | Результат |
|-------------------|-------------------|-----------|
| null или строка | строка | NULL преобразуется в "", числовое или лексическое сравнение |
| булев или null | что угодно | Преобразуется в bool, FALSE < TRUE |
| объект | объект | Встроенные классы могут определять свои собственные правила сравнения, объекты разных классов не сравниваются, объекты одного класса - сравниваются свойства тем же способом, что и в массивах |
| строка или число | строка или число | Строки переводятся в числа, обычная математика |
| массив | массив | Массивы с меньшим числом элементов считаются меньше, если ключ из первого операнда не найден во втором операнде - массивы не могут сравниваться, иначе идет сравнение соответствующих значений |
| объект | что угодно | object всегда больше |
| массим | что угодно | array всегда больше |
### Побитовые операторы
Побитовые операторы позволяют считывать и устанавливать конкретные биты целых чисел.
* `$a | $b` - битовое ИЛИ, устанавливаются те биты, которые установлены в `$a` или в `$b`.
* `$a & $b` - битовое И, устанавливаются только те биты, которые установлены и в `$a`, и в `$b`.
* `$a ^ $b` - битовое исключающее ИЛИ, устанавливаются только те биты, которые установлены либо только в `$a`, либо только в `$b`, но не в обоих одновременно.
* `~$a` - битовое отрицание, устанавливаются те биты, которые не установлены в `$a`, и наоборот.
* `$a << $b` - битовый сдвиг влево, все биты переменной `$a` сдвигаются на `$b` позиций влево (каждая позиция подразумевает "умножение на 2")
* `$a >> $b` - битовый сдвиг вправо, все биты переменной `$a` сдвигаются на `$b` позиций вправо (каждая позиция подразумевает "деление на 2")
```smarty
{if $a & 1} {var $b = 4 | $flags} {/if}
```
### Оператор присваивания
Базовый оператор присваивания обозначается как `=`. На первый взгляд может показаться, что это оператор "равно".
На самом деле это не так. В действительности, оператор присваивания означает, что левый операнд получает значение правого выражения,
(т.е. устанавливается значением).
В дополнение к базовому оператору присваивания имеются "комбинированные операторы" для всех бинарных арифметических операций и строковых операций,
которые позволяют использовать некоторое значение в выражении, а затем установить его как результат данного выражения.
То есть выражение `$a = $a + 2` может быть записано как `$a += 2`.
* `$a = $b` - присвоение
* `$a += $b` - присвоение с добалением.
* `$a -= $b` - присвоение с вычитанием.
* `$a *= $b` - присвоение с умножением.
* `$a /= $b` - присвоение с делением.
* `$a %= $b` - присвоение с делением по модулю.
* `$a &= $b` - присвоение с битовыйм И.
* `$a |= $b` - присвоение с битовыйм ИЛИ.
* `$a ^= $b` - присвоение с битовыйм исключением ИЛИ
* `$a <<= $b` - присвоение с битовым сдвигом влево.
* `$a >>= $b` - присвоение с битовым сдвигом врпаво.
```smarty
{set $b |= $flags}
```
### Операторы инкремента и декремента
Fenom поддерживает префиксные и постфиксные операторы инкремента и декремента в стиле PHP или C.
**Замечание:**
Операторы инкремента/декремента не влияют на булевы значения. Декремент NULL также не даст никакого эффекта, однако инкремент даст значение 1.
* `++$a` - префиксный инкремент, увеличивает $a на единицу, затем возвращает значение $a.
* `$a++` - постфиксный инкремент, возвращает значение $a, затем увеличивает $a на единицу.
* `--$a` - префиксный декремент, уменьшает $a на единицу, затем возвращает значение $a.
* `$a--` - постфиксный декремент, возвращает значение $a, затем уменьшает $a на единицу.
### Строковые операторы
Оператор объединения `~` возвращает строку, представляющую собой соединение левого и правого аргумента.
* `$a ~ $b` - возвращает результат объединения сток `$a` и `$b`
* `$a ~~ $b` - возвращает результат объединения сток `$a` и `$b` через пробел
* `$a ~= $b` - присвоение с объединением
Примеры
```smarty
{"A" ~ "B"} -> AB
{"A" ~~ "B"} -> A B
{add $v = "A"}
{set $v ~= "B"}
{$v} -> AB
```
### Оператор интервала
Оператор `..` позволяет создать массив данных, не выходящих за указанные пределы.
```smarty
{set $a = 1..4}
```
создаст массив `[1,2,3,4]`
```smarty
{set $a = 'a'..'f'}
```
создаст массив `['a','b','c','d','e','f']`
```smarty
{set $a = 'a'|up..'f'|up}
```
создаст массив `['A','B','C','D','E','F']`
```smarty
{set $a = $min..$max}
```
создаст массив из значений где первый (минимальный) элемент будет иметь значение `$min`,
а максимальный (последний) элемент будет иметь значение `$max`
**Замечание:**
ограничения должны быть одного типа, интервал `1..'f'` преобразует `f` в `0` и будет сгенерировано `[1,0]`
### Тернарные операторы
Еще одним условным оператором являются тернарные операторы `?:` и `!:`.
Выражения `(expr1) ? (expr2) : (expr3)` и `(expr1) ! (expr2) : (expr3)` интерпретируется как `expr2`, если `expr1` имеет значение TRUE, или как `expr3` если `expr1` имеет значение FALSE.
Тернарый оператор `?:` проверяет условие `expr1` на не "пустое" значение, то есть `expr1` при конвертирование в булевое значение должен вернуть TRUE.
Следующие значения воспринимаются как пустые:
* "" (пустая строка)
* 0 (целое число)
* 0.0 (дробное число)
* "0" (строка)
* NULL
* FALSE
* array() (пустой массив)
* переменная не объявлена
* элемента массива не существует
* свойство объекта не существует
```smarty
{$request.action ? $request.action : 'default'}
```
Пример выше стоит интерпретировать так: если `$request.action` не пустое то вернуть `$request.action` иначе вернуть `default`.
Приведенный пример можно записать в упрощенном формате:
```smarty
{$request.action ?: 'default'}
```
Тернарый оператор `?:` проверяет условие `expr1` на существование и относится больше к работе с переменными,
то есть переменная в выражении `expr1` должна существовать даже если она "пустая", но не NULL.
Данный оператор не имеет значения если `expr1` функция или метод, так как в этом случае всегда будет TRUE.
```smarty
{$request.action ! $request.action : 'default'}
```
Пример выше стоит интерпретировать так: если переменна я `$request` существует, является массивом и существует ключ `$request.action` то вернуть `$request.action` иначе вернуть `default`.
Приведенный пример можно записать в упрощенном формате:
```smarty
{$request.action !: 'default'}
```
Как видно, оператор `:?` более расширенный чем `:!` и включает в себя функциональность оператора `!:`.
Для упрощения понимания можно подвести итог:
* `$a ? $b : $c` - вернет `$b` если `$a` не пустое, иначе вернет `$c`.
* `$a ! $b : $c` - вернет `$b` если `$a` существует, иначе вернет `$c`.
* `$a ?: $b` - вернет `$a` если `$a` не пустое, иначе вернет `$b`.
* `$a !: $b` - вернет `$a` если `$a` существует, иначе вернет `$b`.
```smarty
{var $a = true}
{$a ? 5 : 10} {* вернет 5 *}
{var $a = false}
{$a ? 5 : 10} {* вернет 10 *}
```
### Операторы проверки
Оператор проверки это упрощенный тернарный оператор от которого осталась только часть проверки без возвращаемых вариантов.
Суть операторов — быстро произвести проверку на не пустое значение и существование пременной.
* `$a?` - вернет `TRUE` если `$a` не пустое
* `$a!` - вернет `TRUE` если `$a` существует
```smarty
{if $a?} {* вместо {if !empty($a)} *}
{if $a!} {* вместо {if isset($a)} *}
```
### Оператор тестирования
Оператор `is` производит тесты над переменными или выражением. Левый операнд считается тестируемым, а правый операнд — название теста:
```smarty
{* проверка переменной на не четность *}
{$a is odd}
```
Результат тестирования может быть инвертирован с помощью `is not` оператора:
```smarty
{* проверяем переменную что ее значение не является числом *}
{$a is not integer}
```
Список допустимых тестов:
* `$a is integer` - тестирует перменную на тип. Тестом может быть
* `int`, `integer` — целое число
* `bool`, `boolean` — булево значение
* `float`, `double`, `decimal` - дробное число
* `array` — массив
* `object` — объект
* `scalar` — скалярное значение (не массив и не объект)
* `string` — строка
* `callback`, `callable` — функция
* `number`, `numeric` — число, в общем понимании
* `$a is iterable` - тестирует переменную на возможность итеративного обхода (для `foreach`).
* `$a is template` - переменная `$a` содержит название существующего шаблона.
* `$a is empty` - переменная пустая.
* `$a is set` - переменная существует.
* `$a is even` - переменная `$a` имеет четное значение.
* `$a is odd` - переменная `$a` имеет не четное значение.
* `$a is MyClass` или `$a is \MyClass` - переменная `$a` является сущностью класса `MyClass`
* `$a is $b` - `$a` тождественна `$b`
### Оператор присутствия
Оператор `in` проверяет присутствие скалярного значения слева в массиве или строке справа.
Результат тестирования может быть инвертирован с помощью `not ni` оператора.
* `$a in list $b` - значение `$a` содержится в массиве значений `$b`
* `$a in keys $b` - массив `$b` имеет ключ `$a`
* `$a in string $b` - значение `$a` содержится в `$b` как подстрока.
* `$a in $b` - значение `$a` содержится в `$b`, где `$b` может быть строкой, обычным или ассоциативным массивом.
Этот вариант долгий так как требуется проверить типы переменной `$b`.
Однако если вместо $b явно задан массив или строка то оператор сам адаптируется для быстрого поиска.
```smarty
{'df' in 'abcdefg'}
{5 in [1, 5, 25, 125]}
{99 in keys [1, 5, 25, 99 => 125]}
```