Выражения
В Ficus можно пользоваться обычным набором арифметических выражений. Кроме того, поскольку это фукнциональный язык, многие управляющие конструкции, выполненные как операторы в императивных языка, также являются выражениями и их можно использовать в других выражениях:
val rng = RNG(0x123u64)
println(if bool(rng) {"головы"} else {"хвосты"})
Обратите внимание, что if не является тернарной операцией, как в C/C++, это полноценный условный оператор, внутрь веток then и elseкоторого можно вкладывать любое корректное выражение, включая определение значей и функций и пр.
Операции являются основой выражений. В таблице представлены операции, отсортированные по приоритетам (от низшего к высшему):
| Операция | Приоритет | Ассоциативность | Тип результата | Описание |
|---|---|---|---|---|
exp1 = exp2 | 1 | левая | void | присвоить новое значение |
exp1 op= exp2 | 1 | левая | void | дополненное выражение присваивания |
exp1 : typespec | 2 | N/A | typespec | аннотация типа |
exp1 :> typespec | 2 | левая | typespec | приведение типа |
exp1 : exp2 : exp3 | 2 | левая | диапазон | построение диапазона |
exp1 : exp2 | 2 | левая | диапазон | эквивалентно выражению exp1:exp2:1 |
exp1 \|\| exp2 | 3 | левая | bool | логическое ИЛИ |
exp2 && exp2 | 4 | левая | bool | логическое И |
exp1 == exp2 | 5 | левая | bool | равенство |
exp1 != exp2 | 5 | левая | bool | неравенство |
exp1 < exp2 | 5 | левая | bool | меньше |
exp1 <= exp2 | 5 | левая | bool | меньше или равно |
exp1 >= exp2 | 5 | левая | bool | больше или равно |
exp1 > exp2 | 5 | левая | bool | больше |
elem :: list | 6 | правая | как у list | сконструировать список |
exp1 \| exp2 | 7 | левая | как у аргументов | побитовое ИЛИ |
exp1 ^ exp2 | 8 | левая | как у аргументов | побитовое “исключающее ИЛИ” |
exp1 & exp2 | 9 | левая | как у аргументов | побитовое И |
exp1 <=> exp2 | 10 | левая | int | оператор “космический корабль” |
exp1 .cmpop exp2 | 11 | левая | коллекция bool | поэлементное сравнение |
exp1 .<=> exp2 | 12 | левая | коллекция int | поэлементный “космический корабль” |
exp1 === exp2 | 12 | левая | bool | операция эквивалентности |
exp1 << exp2 | 13 | левая | как у exp1 | сдвиг влево |
exp1 >> exp2 | 13 | левая | как у exp1 | сдвиг вправо |
exp1 + exp2 | 14 | левая | объединенный тип | сложение |
exp1 - exp2 | 14 | левая | объединенный тип | вычитание |
exp1 .+ exp2 | 14 | левая | объединенная коллекция | поэлементное сложение |
exp1 .- exp2 | 14 | левая | объединенная коллекция | поэлементное вычитание |
exp1 * exp2 | 15 | левая | объединенный тип | поэлементное умножение |
exp1 / exp2 | 15 | левая | объединенный тип | поэлементное деление |
exp1 % exp2 | 15 | левая | объединенный тип | знаковый остаток |
exp1 \ exp2 | 15 | левая | как у exp1 | обратное деление |
seq * n | 15 | левая | как у seq | повторить seq n раз |
n * seq | 15 | левая | как у seq | повторить seq n раз |
exp1 .* exp2 | 15 | левая | объединенная коллекция | поэлементное умножение |
exp1 ./ exp2 | 15 | левая | объединенная коллекция | поэлементное деление |
exp1 ** exp2 | 16 | правая | объединенный тип | возведение в степень |
exp1 .** exp2 | 16 | правая | объединенная коллекция | поэлементное возведение в степень |
+exp, -exp | 17 | правая | объединенный тип | унарный плюс, унарный минус |
.-exp | 17 | правая | объединенный тип | унарный точка-минус |
!exp | 17 | правая | bool | логическое отрицание |
~exp | 17 | правая | как у exp | побитовое отрицание |
\exp | 17 | правая | N/A | операция развертывания |
ref exp | 17 | правая | ссылка | создание ссылки с начальным значением exp |
exp' | 18 | левая | как у exp | транспонирование массива |
*exp | 19 | правая | тип по ссылке | разыменование ссылки |
exp1.name | 20 | левая | тип члена | доступ к членам |
exp1->name | 20 | левая | тип члена | разыменование и доступ |
exp1.X | 20 | левая | тип члена | доступ к полю X кортежа |
exp1->X | 20 | левая | тип члена | разыменование и доступ |
exp1.{name2=exp2,...} | 20 | левая | запись | измененная копия записи |
exp1->{name2=exp2,...} | 20 | левая | запись | как предыдущее, с разыменованием |
exp1[exp2,exp3,...] | 20 | левая | тип элемента | доступ к элементу или подмассиву |
exp1(exp2,exp3,...) | 20 | левая | тип возврата | вызов функции |
(exp1) | ∞ | N/A | как у exp1 | управление порядком вычислений |
({code_block ...}) | ∞ | N/A | тип последнего exp | как предыдущее |
(exp1, exp2, ...) | ∞ | N/A | кортеж | создание кортежа |
[exp1, exp2, ...] | ∞ | N/A | массив | создание массива |
[:: exp1, exp2, ...] | ∞ | N/A | список | создание списка |
[for ...] | ∞ | N/A | массив | построение массива |
[:: for ...] | ∞ | N/A | список | построение списка |
(:: for ...) | ∞ | N/A | кортеж | построение кортежа |
name1 {name2=exp2,...} | ∞ | N/A | запись | создание записи |
Как и в других языках, приоритеты операций и правила ассоциации часто уменьшают необходимость использования скобок ( ), но при необходимости можете их использовать для изменения порядка вычислений.
Что обозначает объединенный тип в табице? Это тип, вычисляемый из T1 и T2, достаточно широкий, чтобы избежать (в большинстве случаев) усечения результата операции. Развернутое определение объединения дается в разделе Числа.
Помимо основных операций, показанных в таблице, есть и другие, описанные в соответствующих разделах.