открыть: Синтаксис 3Syntax 2открыть: Синтаксис 1

Операторы

Информация на этой странице устарела и находится в процессе обновления.

Сравнение

a == b -- равенство a <> b -- неравенство a < b -- меньше_чем a > b -- больше_чем a <= b -- меньше_или_равно a >= b -- больше_или_равно a <=> b -- -1, если a < b; 0, если a == b; +1, если a > b;

Сравнение значений разных типов равнозначно сравнению порядковых номеров этих типов. Исключением из этого правила является сравнение значений между типами $int# и $float#. Чтобы узнать порядковый номер типа необходимо преобразовать этот тип в $int#, используя команду as.

v.type_id = $null# as $int# -- v.type_id = 0 v.var = #1 v.type_id = v.var &type as $int# -- v.type_id = $bool# as $int#

Порядковые номера у каждого типа могут различаться в разных версиях языка ksi. Однако стандарт гарантирует, что порядковый номер у типа $null# всегда равен 0.

При вызове операторов сравнения по цепочке, кроме оператора <=>, работают ленивые вычисления.

-- выражение 1: v.a < v.b < v.c <= v.d == 0 > v.x -- почти аналогично выражению 2: (v.a < v.b) && (v.b < v.c) && (v.c <= v.d) && (v.d == 0) && (0 > v.x)

В приведённом выше примере результат выражений 1 и 2 будет одинаковым. Только выражение 1 преобразуется интерпретатором в меньшее количество инструкций и следовательно работает быстрее.

Арифметические операторы

a + b a - b a * b a / b a mod b -- остаток от деления

Логические

a && b -- И * a || b -- ИЛИ * a ^^ b -- ЛИБО (исключающее или) a not -- отрицание

* Используются ленивые вычисления.

Результат выражения a && b зависит от a. Если a после преобразования в тип $bool# равно false #0, то результатом будет a (до преобразования), и выражение b не будет вычисляться. Иначе результатом будет b.

Выражение a || b работает похожим образом. Если a после преобразования в тип $bool равно true #1, то результат будет a (до преобразования), и выражение b не будет вычисляться. Иначе результатом будет b.

Логика выражения a ^^ b немного сложнее. Сперва вычисляются выражения a и b, а их результаты преобразуются в тип $bool# – назовём их bool_a и bool_b. Если bool_b равно false #0, то результат всего выражения равен a. Если bool_b равно true #1 и bool_a равно false #0, то результат всего выражения равен b. Иначе результат всего выражения равен false #0.

Побитовые

a & b -- побитовое И a | b -- побитовое ИЛИ a ^ b -- побитовое исключающее или a not_bits -- инвертировать биты

Текстовые

a % b -- конкатенация строк текста a %% b -- обратная конкатенация (a %% b == b % a)

Присваивание

-- Одиночное присваивание: v.a = 5 -- Групповое присваивание: (v.x v.y v.z) = # -- x = #, y = #, z = # -- Массивное присваивание: array (v.a # v.c) = array (1 2 3) -- a = 1, c = 3 -- Ассоциативное присваивание: map (key1: v.x, key2: v.y) = map ( key1: 'раз' key2: 'два' key3: 'три' ) -- x = 'раз', y = 'два'

Групповое, массивное и ассоциативное присваивание пока не реализовано в интерпретаторе.

В ksi также есть оператор присвоения вправо:

-- Одиночное: 5 => v.a -- Групповое: # => (v.x v.y v.z) -- x = #, y = #, z = # -- Массивное: array (1 2 3) => array (v.a # v.c) -- a = 1, c = 3 -- Ассоциативное: map ( :key1 : 'раз' :key2 : 'два' :key3 : 'три' ) => map ('key1' : v.x, 'key2' : v.y) -- x = 'раз', y = 'два'

Групповое, массивное и ассоциативное присваивание вправо пока не реализовано в интерпретаторе.

Составное присвоение

v.a += 1 -- v.a = v.a + 1 2 /=> v.a -- v.a / 2 => v.a += +=> -= -=> *= *=> /= /=> mod= mod=> %= %=> %%= %%=> &&= &&=> -- * ||= ||=> -- * ^^= ^^=> &= &=> |= |=> ^= ^=> ??= ??=> -- *

* Используются ленивые вычисления.

Составное присвоение сможет также быть одновременно и групповым, массивным или ассоциативным, когда такая конструкция получит поддержку в интерпретаторе.

(v.a v.b) += 1 (v.x v.y) ??= (v.array &implode: "") /* Правая часть от ленивого оператора ??= будет вычислена не более одного раза. А может быть и не вычислена совсем. */

Составное присвоение с вызовом функции

Пока не реализовано в интерпретаторе.

v.a &fn_call: = v.b -- v.a = v.a &fn_call: v.b v.a &fn_call:> = v.b -- v.a = v.b &fn_call: v.a

Префиксная форма

Открывающая скобочка, префиксный оператор, список выражений, перечисленных через необязательную запятую, закрывающая скобочка. Перед закрывающей скобкой можно поставить запятую – она ни на что не повлияет.

(+ 1,2,3) => v.x -- v.x = 6 (+ 1 2 3) => v.x -- запятые не обязательны (% %hello, ' ', "world!") => v.t &write -- вывод: hello world! (&& v.a v.b v.c) -- v.a && v.b && v.c (?? #, (v.x = [], v.x.0), 'default') -- # ?? (v.x = [], v.x.0) ?? 'default'

Количество выражений после префиксного оператора должно быть не меньше двух, иначе будет ошибка загрузки скрипта. Присваивание не может быть использовано в качестве префиксного оператора.

Обращение к элементам составных типов

Для обращения к элементу составного типа (массив, мапа, объект класса) в языке ksi существуют два оператора – это точка . и квадратные скобочки v.var[v.key]. Между переменной и квадратными скобочками не должно быть пробелов.

После оператора точка может следовать целое число или слово. Однако в контексте присвоения значения после точки может идти дополнительно и такие значения, как: #0, #1, #. Контекст присвоения – это операнд слева от оператора = (а также их составных вариантов), или справа от оператора => (а также их составных вариантов).

-- следующие три строки аналогичны: v.var.# = 5 v.var[] = 5 v.var[#] = 5 -- следующие две строки аналогичны: v.var.#1 = # v.var[#1] = # -- следующие две строки аналогичны: v.var.0 = 1 v.var[0] = 1 -- следующие три строки аналогичны: v.var.x = 'hello' v.var[:x] = 'hello' v.var['x'] = 'hello' v.x = v.var[#0] -- ошибки нет v.x = v.var.#0 -- ошибка этапа загрузки скрипта 'parse error' v.x = v.var.# -- тоже ошибка 'parse error'

Внутри оператора var[] может быть несколько выражений, перечисленных через необязательную запятую.

-- следующие пять строчек аналогичны: v.x = v.var[1 2 3] v.x = v.var[1][2][3] v.x = v.var[1].2[3] v.x = v.var[1 2].3 v.x = v.var[1, 1+1, 3]

Оператор взятия типа

Для того, чтобы получить тип значения, которое хранится в переменной – поставьте символ $ непосредственно после этой переменной.

v.a = "hello" v.type_of_a = v.a$

Таким образом можно также определять тип константы или элемента коллекции.

v.type = $float.pi#$ -- v.type = $float# v.array = array (10) v.type = v.array[0]$ -- v.type = $int# v.map = map (msg: 'hello') v.type = v.map.msg$ -- v.type = $text#

Работа с функциями

Оператор восклицательный знак ! служит для вызова функции через указатель.

&sum args (a b) body ( ret = (p.a + p.b) ) plain v.fn = &sum.function -- указатель на функцию v.x = 10 v.y = -10 v.z = v.x !v.fn: y -- вызов &sum через указатель v.z &write -- Выдаст: 0

Указатель на функцию и оператор восклицательный знак ! пока не реализованы в интерпретаторе.

Оператор сцепления с null

Выражение a ?? b возвращает a, если оно не null. Иначе вернёт b.

v.n = # v.array = array (0, 1) v.map = map (x: 0, y: 0) v.check = v.n ?? v.array.10 ?? v.map.z ?? 'default' v.check &write -- выдаст: default

Оператор ?? использует ленивые вычисления. Это значит если результат всего выражения известен после вычисления только левой части, то правая часть не будет выполнена.

v.n = #1 ret = v.n ?? (array (%hello space# %world) &implode) -- Здесь функция &implode не будет вызвана совсем.

Оператор сцепления с null можно использовать в сочетании с присваиванием: _переменная_ ??= _выражение_ или _выражение_ ??=> _переменная_. Такая конструкция использует ленивые вычисления, это значит что если _переменная_ не равна null, то всё _выражение_ не будет вычисляться и присвоение не произойдёт.

v.items = array () v.items.0 ??= 1 -- Присвоит 1, так как (v.items.0 == #) v.items.0 ??= 2 -- Не присвоит 2, так как (v.items.0 <> #) v.items &dump: #0 -- Выдаст: array (1)