На этой странице:
Внимание
Для тестирования сценариев, содержащих BPL-операции, необходимо использовать веб-виджет или интеграцию с каким-либо мессенджером, так как данные операции не работают в тестовом чате внутри редактора.
Создание тестового виджета.В блоке операций/выражений можно указывать произвольное количество операций, которые должен выполнить бот в процессе своей работы. Операции представляют собой выражения, записанные с помощью подмножества языка программирования разговорных ботов, описание которого содержится ниже.
Структура операций
Все операции бота в пределах одного блока операций представляют собой одно или несколько выражений на языке программирования ботов. Выражения отделяются друг от друга необязательным символом ";" либо символом перевода строки (началом новой строки). Каждое выражение имеет значение. Это значит, что выражения могут быть составными.
Комментарии
При записи выражений можно указывать комментарии – участки программы, которые не участвуют в вычислениях, а выполняют лишь информационную функцию. Есть два вида комментариев:
- Однострочные. Такие комментарии начинаются с символов // и заканчиваются окончанием строки.
- Многострочные. Начало многострочного комментария начинается с символов /* и заканчивается символами */.
// Это однострочный комментарий $x = time() /** * А это уже * многострочный * комментарий */ say("Time is " + $x)
Переменные
Для хранения данных в сценариях ботов применяются переменные. Переменная представляет собой именованный участок памяти бота. Она создаётся при первом своем использовании в каком-либо блоке операция. При этом значением по умолчанию для всех переменных является nil.
Существует три вида переменных, различающихся своей областью видимости:
- Переменные, видимые в пределах одного модуля в одном потоке.
Доступны для чтения и записи. Названия таких переменных начинаются с символа $. Такие переменные удобно использовать для хранения значений промежуточных операций и вычислений. - Переменные, видимые в пределах одного модуля в разных потоках.
Доступны для чтения и записи. Названия переменных уровня модуля начинаются с символа #. Поскольку такие переменные видны во всех потоках бота их удобно использовать для взаимодействия между потоками. - Глобальные переменные или переменные окружения.
Автоматически задаваемые переменные, которые видны во всех потоках всех модулей бота. Эти переменные доступны только для чтения и хранят информацию о глобальном контексте работы бота. Их имена начинаются с символа @.
// Переменные $p и $r доступны только в потоке, в котором они определены $p = 2 * 3.14 * $r // Эта переменная доступна во всех потоках в пределах текущего модуля // (модуля, в котором находится блок операций, в котором определена переменная). #count = queue.size() // @communicationType глобальная переменная только для чтения. Доступна везде. $isChat = @communicationType == "TEXT"
Имена переменных могут содержать только цифры, английские и русские буквы, а также символ подчёркивания. Т.е. вы не можете назвать переменную каким-то словом, содержащим пробел или символ отличный от символов русского и английского языков. Тем не менее, существует способ использовать любое название. Для этого необходимо заключить название переменной в круглые скобки.
$('日本') = 123 // Создали переменную c именем 日本 $x = $('日本') // $x теперь равна 123 $(math.rand(1, 2)) = 0 // Динамически создаём переменную с именем 1 или 2 и присваиваем ей значение 0
Переменные переменных
Язык выражений бота позволяет вычислять имя переменной динамически в процессе работы бота. Это означает, что значением одной переменной может быть имя другой переменной или любое выражение, значением которого является строка.
В примере ниже мы определяем три переменные, содержащие названия цветов. Затем мы определяем случайно число от 1 до 3 и далее формируем название одной из переменных с тем, чтобы узнать значение случайного цвета.
// Создадим три переменные с именами x1, x2 и x3 $x1 = "red" $x2 = "blue" $x3 = "green" // Случайное число от 1 до 3 $n = math.rand(1, 3) // Получаем цвет динамически сформировав имя переменной с цветом и взяв её значение $color = $("x" :: $n)
Можно также использовать значения переменных разных типов.
// $x содержит название переменной #y $x = "y" // #y содержит название глобальной переменной communicationType #y = "communicationType" // Вычисляется так @#$x -> @#("y") -> @#y -> @("communicationType") -> @communicationType $communicationType = @#$x
Типы данных
Существует три примитивных типа данных, один объектный тип и специальное значение nil.
Числа
Все числа трактуются как вещественные знаковые с плавающей точкой. Минимальное и максимальное значения определяются той вычислительной средой, в которой работает интерпретатор языка выражений.
Строки
Представляют собой произвольную последовательность символов, заключённую в одинарные или двойные кавычки. Двойные кавычки отличаются от одинарных тем, что внутри них распознаются следующие специальные последовательности символов.
Последовательность | Значение |
---|---|
\n | Перевод строки |
\r | Возврат каретки |
\t | Горизонтальная табуляция |
\v | |
\" | Двойная кавычка |
В одинарных кавычках все символы трактуются как есть за исключением последовательности символов \', которая означает символ одинарной кавычки.
// Следующая команда выведет в чат фразу из двух строк // Привет // "Медвед!" say("Привет\n\"Медвед!\"") // Выведет в чат фразу Привет\n'Медвед!' say('Привет\n\'Медвед!\'')
Булевы (логические) значения
Константы true и false трактуются как булевы, т.е. такие значения, у которых есть только два состояния – истина и ложь. Булевы значения удобно применять в выражениях условного блока.
$x = true // $x содержит ИСТИНА $y = !$x // $y содержит ЛОЖЬ
Объекты
В стандартной библиотеке языка программирования бота существует ряд функций (операций), значением которых являются так называемые объекты. Объект – это особое значение, у которого могут быть встроенные свойства и операции или методы. Набор этих свойств и методов определяется типом объекта. Для доступа к свойствам или методам объектов используется оператор точка ".".
Например, с помощью следующего кода можно получить первое сообщение клиента, которое является объектом ClientMessage и далее получить свойство message (текст сообщения) этого объекта.
// $first содержит значение объекта ClientMessage $first = queue.first() // Получаем значение свойства message $firstMessage = $first.message
Свойства и методы объектов (также как и значения переменных) могут быть вычисляемыми.
$n = rand(0, 1) // $n содержит или 0 или 1 $method = ["first", "last"].get($n) // $method содержит строку first или last (см. получение элемента списка по индексу) $firstOrLast = queue.$method // Получаем первое или последнее сообщение клиента // Или даже так $firstOrLast = queue.(["first", "last"].get($n))
Существует три типа встроенных объектов являющихся коллекциями произвольных элементов.
Кортежи
Кортеж или tuple – это неизменяемая, упорядоченная коллекция произвольных элементов. Создать кортеж можно с помощью круглых скобок.
$items = (1, 2, 2) // Кортеж из трёх элементов. $items = ('a',) // Кортеж из одного элемента. Запятая необходима, чтобы отличать создание кортежа от просто круглых скобок. $items = () // Кортеж не содержащий ни одного элемента (пустой кортеж).
Для работы с кортежами доступны следующие методы.
Метод | Описание | Пример | Результат | |
---|---|---|---|---|
1 | count() | Получение количества элементов кортежа | (1, 2, 3).count() | 3 |
2 | first() | Получение первого элемента кортежа | (1, 2, 3).first() | 1 |
3 | last() | Получение последнего элемента кортежа | (1, 2, 3).last() | 3 |
4 | has(index) | Возвращает true, если кортеж содержит элемент с указанным порядковым номером, и false в противном случае | (1, 2, 3).has(0) | true false |
5 | get(index) | Возвращает элемент кортежа по его порядковому номеру или nil, если такого элемента нет | (1, 2, 3).get(1) | 2 |
6 | contains(item) | Возвращает 1, если кортеж содержит элемент item, и ничего (void) в противном случае. | (1, 2, 3).contains(3) | true |
7 | index(item) | Возвращает порядковый номер элемента item либо -1, если такого элемента нет | (1, 2, 3).index(3) | 2 |
8 | equals(other) | Возвращает true, если other представляет собой точно такой же кортеж (т.е. кортеж, содержащий те же самые элементы), и false в противном случае | ('a', 'b').equals(('a', 'b')) | true false |
9 | hash() | Возвращает строку, представляющую собой хэш кортежа (значение, уникально идентифицирующее содержимое кортежа) | ('a', true).hash() | bb2fadd01f7d0ac9864dc963a61f653f |
10 | copy() | Создаёт поверхностную копию кортежа (т.е. не копирует коллекции внутри кортежа). | $list = ["a", "b"] $copy = (1, 2, $list).copy() $copy.get(2).append("c") | $list будет равен |
11 | deepCopy() | Создаёт полную копию кортежа. | $list = ["a", "b"] | $list будет равен |
12 | merge(collection) | Возвращает новый кортеж полученный из слияния текущего кортежа с коллекций (другим кортежем, списком или словарём) | (1, 2, 3).merge((4, 5)) | (1, 2, 3, 4, 5) |
Списки
Список или list – это изменяемая, упорядоченная коллекция произвольных элементов. Создать список можно с помощью квадратных скобок.
$items = [1, 2, 2] // Список из трёх элементов $items = ['a'] // Список из одного элемента $items = [] // Список не содержащий ни одного элемента (пустой список)
Для работы со списками доступны следующие методы.
Метод | Описание | Пример | Результат |
---|---|---|---|
count() | Получение количества элементов списка | [1, 2, 3].count() | 3 |
first() | Получение первого элемента списка | [1, 2, 3].first() | 1 |
last() | Получение последнего элемента списка | [1, 2, 3].last() | 3 |
has(index) | Возвращает true, если список содержит элемент с указанным порядковым номером, и false в противном случае | [1, 2, 3].has(0) | true false |
get(index) | Возвращает элемент списка по его порядковому номеру или nil, если такого элемента нет | [1, 2, 3].get(1) | 2 |
contains(item) | Возвращает true, если список содержит элемент item, и false в противном случае | [1, 2, 3].contains(1) | true |
index(item) | Возвращает порядковый номер элемента item либо -1, если такого элемента нет | [1, 2, 3].index(1) | 0 |
toTuple() | Возвращает кортеж, состоящий из элементов данного списка | [1, 2, 3].toTuple() | (1, 2, 3) |
clear() | Удаляет все элементы списка | $x = [1, 2, 3] | $x содержит пустой список [] |
reverse() | Меняет порядок следования элементов списка на обратный | [1, 2, 3].reverse() | [3, 2, 1] |
append(item) | Добавляет переданное значение item в конец списка | [1, 2, 3].append(4) | [1, 2, 3, 4] |
prepend(item) | Добавляет переданное значение item в начало списка | [1, 2, 3].prepend(0) | [0, 1, 2, 3] |
shift() | Удаляет и возвращает первый элемент списка | $x = [1, 2, 3] | $y будет содержать 1, а $x станет равным [2, 3] |
pop() | Удаляет и возвращает последний элемент списка | $x = [1, 2, 3] | $y будет содержать 3, а $x станет равным [1, 2] |
set(index, item) | Добавляет значение в указанную позицию списка. Если позиция лежит за пределами списка, то он будет расширен нулевыми значениями до нужного размера. | $x = [1, 2, 3] | $y содержит [1, 0, 3] |
remove(index) | Удаляет элемент списка в указанной позиции и возвращает его значение | $x = [1, 2, 3] | $y будет содержать 2, а $x станет равным [1, 3] |
equals(other) | Возвращает true, если other представляет собой точно такой же список (т.е. список, содержащий те же самые элементы), и false в противном случае | ['a', 'b'].equals(['a', 'b']) | true false |
hash() | Возвращает строку, представляющую собой хэш списка (значение, уникально идентифицирующее содержимое списка) | ['a', true].hash() | bb2fadd01f7d0ac9864dc963a61f653f |
copy() | Создаёт поверхностную копию списка (т.е. не копирует коллекции внутри списка). | $list = ["a", "b"] $copy = [1, 2, $list].copy() $copy.get(2).append("c") | $list будет равен ["a", "b", "c"] $copy будет равен [1, 2, ["a", "b", "c"]] |
deepCopy() | Создаёт полную копию списка. | $list = ["a", "b"] $copy = [1, 2, $list].deepCopy() $copy.get(2).append("c") | $list будет равен ["a", "b"] $copy будет равен [1, 2, ["a", "b", "c"]] |
merge(collection) | Сливает текущий список с коллекций (другим кортежем, списком или словарём) и возвращает его. | ["a", "b"].merge((1, 2)) | ["a", "b", 1, 2] ["a", "b", "a", "c"] ["a", "b", 1, 2] |
Ассоциативные массивы (словари)
Ассоциативный массив или словарь (map) – это изменяемая, упорядоченная коллекция произвольных пар ключ/значение. Создаётся словарь с помощью фигурных скобок.
$items = {'a': 1, 'b': 2, 'c': 3} // Словарь из трёх элементов $items = {'a': true} // Cловарь из одного элемента $items = {} // Словарь, не содержащий ни одного значения (пустой словарь)
Для работы со словарями доступны следующие методы.
Метод | Описание | Пример | Результат |
---|---|---|---|
count() | Получение количества элементов словаря | {1: 'a', 2: 'b', 3: 'c'}.count() | 3 |
clear() | Удаление всех элементов словаря | $x = {true: false, 'b': true} | $x будет содержать пустой словарь |
reverse() | Меняет порядок следования элементов словаря на обратный | {'a': 1, 'b': 2, 'c': 3}.reverse() | {'c': 3, 'b': 2, 'a': 1} |
values() | Возвращает список, состоящий из всех значений словаря | {'a': 1, 'b': 2, 'c': 3}.values() | [1, 2, 3] |
keys() | Возвращает список, состоящий из всех ключей словаря | {'a': 1, 'b': 2, 'c': 3}.keys() | ['a', 'b', 'c'] |
firstKey() | Получение первого ключа словаря | {'a': 1, 'b': 2, 'c': 3}.firstKey() | 'a' |
lastKey() | Получение последнего ключа словаря | {'a': 1, 'b': 2, 'c': 3}.lastKey() | 'c' |
first() | Получение первого элемента словаря | {'a': 1, 'b': 2, 'c': 3}.first() | 1 |
last() | Получение последнего элемента словаря | {'a': 1, 'b': 2, 'c': 3}.last() | 3 |
contains(item) | Возвращает true, если словарь содержит элемент item, и false в противном случае | {'a': 1, 'b': 2, 'c': 3}.contains(2) | true |
key(item) | Возвращает ключ, соответствующий значению item, или nil в противном случае | {'a': 1, 'b': 2, 'c': 3}.key(3) | c |
has(key) | Возвращает true, если элемент с указанным ключом сущеcтвует, и false в противном случае | {'a': 1, 'b': 2, 'c': 3}.has('a') | true |
get(key) | Возвращает элемент словаря по его ключу или nil, если такого элемента нет | {'a': 1, 'b': 2, 'c': 3}.get('b') | 2 |
set(key, item) | Устанавливает элемент словаря с заданным ключом | $x = {1: true, 2: nil} | $x будет содержать {1: true, 2: false} |
remove(key) | Удаляет элемент словаря по ключу и возвращает его значение | $x = {'a': 1, 'b': 2} | $y будет содержать 1, а $x станет равным {'b': 2} |
equals(other) | Возвращает true, если other представляет собой точно такой же словарь (т.е. словарь, содержащий те же самые ключи и значения), и false в противном случае | {'a': 'b'}.equals(['a': 'b']) | true false |
hash() | Возвращает строку, представляющую собой хэш словаря (значение, уникально идентифицирующее содержимое словаря) | {'a': true}.hash() | bb2fadd01f7d0ac9864dc963a61f653f |
copy() | Создаёт поверхностную копию словаря (т.е. не копирует коллекции внутри словаря). | $list = ["a", "b"] $copy = {"a": 1, "b": $list}.copy() $copy.get("b").append("c") | $list будет равен ["a", "b", "c"] $copy будет равен {"a": 1, "b": ["a", "b", "c"]} |
deepCopy() | Создаёт полную копию словаря. | $list = ["a", "b"] $copy = {"a": 1, "b": $list}.deepCopy() $copy.get("b").append("c") | $list будет равен ["a", "b"] $copy будет равен {"a": 1, "b": ["a", "b", "c"]} |
merge(collection) | Сливает текущий словарь с коллекций (другим кортежем, списком или словарём) и возвращает его. | {"a": true, "b": 123}.merge((1, 2)) | {"a": true, "b": 123, 0: 1, 1: 2} {"a": true, "b": 123, 0: 1, 1: 2} {"a": 321, "b": 123, "c": false} |
Специальное значение nil
Когда какая-либо переменная не определена, но уже используется в выражении, её значением становится nil. Это специальное значение, означающее отсутствие какого-либо значения. Это значение также можно присвоить явно.
$x = 1 + 2 // $x содержит 3 $x = nil // $x содержит nil
Операции
В языке выражений бота определенно несколько бинарных и унарных операций. Некоторые операции могут быть применены к разным типам данных. Тип результата операции определяется видом операции. Например, операция "::" принимает в качестве аргументов строки. Поэтому все операнды этой операции будут неявно преобразованы к строке.
Приоритеты операций
Чем приоритет выше, тем раньше выполнится операция. Стандартным способом увеличения приоритета являются круглые скобки.
Операция | Приоритет | Ассоциативность | Описание |
---|---|---|---|
** | 12 | Правая | Возведение в степень |
+ | 11 | – | Унарный плюс |
- | 11 | - | Унарный минус |
~ | 11 | – | Побитовая инверсия |
! | 10 | – | Логическое отрицание |
* | 9 | Левая | Умножение |
/ | 9 | Левая | Деление |
\ | 9 | Левая | Целочисленное деление |
% | 9 | Левая | Остаток от деления |
+ | 8 | Левая | Сложение |
- | 8 | Левая | Вычитание |
:: | 8 | Левая | Конкатенация строк |
< | 7 | – | Меньше чем |
<= | 7 | – | Меньше или равно |
> | 7 | – | Больше чем |
>= | 7 | – | Больше или равно |
== | 6 | – | Равно |
!= | 6 | – | Не равно |
& | 5 | Левая | Побитовое И |
^ | 4 | Левая | Побитовое исключающее ИЛИ |
| | 3 | Левая | Побитовое ИЛИ |
&& | 2 | Левая | Логическое И |
|| | 1 | Левая | Логическое ИЛИ |
= | 0 | Правая | Присваивание |
+= | 0 | Правая | Сложение с присваиванием |
-= | 0 | Правая | Разность с присваиванием |
::= | 0 | Правая | Конкатенация с присваиванием |
*= | 0 | Правая | Умножение с присваиванием |
/= | 0 | Правая | Деление с присваиванием |
\= | 0 | Правая | Целочисленное деление с присваиванием |
%= | 0 | Правая | Остаток от деления с присваиванием |
**= | 0 | Правая | Возведение в степень с присваиванием |
&= | 0 | Правая | Бинарное И с присваиванием |
^= | 0 | Правая | Бинарное исключающее И с присваиванием |
|= | 0 | Правая | Бинарное ИЛИ с присваиванием |
Арифметические операции
Арифметические операции предназначены для работы с числами. Если значение, участвующее в арифметической операции, не является числом, то произойдёт попытка его преобразования в число (см. ниже).
Пример | Результат |
---|---|
+$a | Преобразование $a в число |
-$a | Смена знака $a |
$a + $b | Сумма $a и $b |
$a - $b | Разность между $a и $b |
$a * $b | Умножение $a на $b |
$a / $b | Деление $a на $b |
$a \ $b | Целочисленное деление $a на $b |
$a % $b | Остаток от деления $a на $b |
$a ** $b | Возведение $a в степень $b |
Побитовые операции
Это отдельный класс операций, предназначенных для выполнения над битовыми представлениями целых чисел.
Пример | Результат |
---|---|
~$a | Устанавливаются те биты, которые не установлены в $a, и наоборот |
$a & $b | Устанавливает только те биты, которые установлены и в $a, и в $b |
$a | $b | Устанавливает те биты, которые установлены в $a или в $b |
$a ^ $b | Устанавливаются только те биты, которые установлены либо только в $a, либо только в $b, но не в оба одновременно |
Таблица преобразования других типов данных в число.
Тип | Значение | Результат |
---|---|---|
NIL | nil | 0 |
Логический | true | 1 |
Логический | false | 0 |
Строка | "" | 0 |
Строка | "123.5" | 123.5 |
Строка | "abc" | ошибка |
Объект | любой | ошибка |
Логические операции
Логические операции предназначены для работы с булевыми значениями. Если значение не является булевым, то произойдёт попытка его преобразования в булево значение (см. ниже).
Пример | Результат |
---|---|
!$a | true, если $a равно false, и false в противном случае |
$a && $b | true, если $a и $b true, false в противном случае |
$a || $b | false, если $a и $b false, true в противном случае |
Таблица преобразования других типов данных в булево значение.
Тип | Значение | Результат |
---|---|---|
NIL | nil | false |
Число | 0 | false |
Число | Любое ненулевое | true |
Строка | "" | false |
Строка | Любая непустая | true |
Объект | Любой | true |
Операции со строками
Есть только одна операция для работы со строками. Это сложение или конкатенация строк.
Пример | Результат |
---|---|
"a" :: "b" | "ab" |
Если аргумент операции конкатенации не является строкой, то он будет преобразован в строку согласно следующей таблицы преобразования.
Тип | Значение | Результат |
---|---|---|
NIL | nil | "" |
Число | 123.45 | "123.45" |
Логический | true | "true" |
Логический | false | "false" |
Объект | Любой | Сериализация в строку |
Операции сравнения
Операции сравнения выполняются над любыми типами данных и результатом их вычисления являются булевы значения.
Пример | Результат |
---|---|
$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 |
Операции с коллекциями
Для встроенных типов объектов tuple, list и map доступна одна операция объединения.
Пример | Результат |
---|---|
(1, 2) + (3, 4) | (1, 2, 3, 4) |
['a', 'b'] + ['c'] | ['a', 'b', 'c'] |
{'a': 0, 'b': 2} + {'a': 1, 'c': 3} | {'a': 1, 'b': 2, 'c': 3} |
Операции присваивания
Операции присваивания позволяют назначать переменным какое-либо значение.
Пример | Результат |
---|---|
$a = 123 | $a содержит 123 |
$a += 1 | $a = $a + 1 |
$a -= 1 | $a = $a - 1 |
$a ::= "b" | $a = $a :: "b" |
$a *= 2 | $a = $a * 2 |
$a /= 2 | $a = $a / 2 |
$a \= 2 | $a = $a \ 2 |
$a %= 5 | $a = $a % 5 |
$a **= 3 | $a = $a ** 3 |
$a &= 1 | $a = $a & 1 |
$a |= 3 | $a = $a | 3 |
$a ^= 4 | $a = $a ^ 4 |
Кроме присваивания значения одной переменной есть возможность присвоить значение сразу нескольким переменным.
Пример | Результат присваивания | Значение выражения присваивания |
---|---|---|
($x, $y, $z) = (1, 2, 3) | $x = 1 | (1, 2, 3) |
[$x, $y] = ($y, $x) | $x = $y | [$y, $x] |
{'a': $x, 'b': $y} = {'b': true, 'a': false} | $x = false | {'a': false, 'b': true} |
($x, $y, $z) += [1, 2, 3] | $x = $x + 1 | ($x + 1, $y + 1, $z + 1) |
{3: $x, 7: $y} *= (2, 3) | $x = $x * 2 | {3: $x * 2, 7: $y * 3} |
Функции
Основными строительными элементами выражений в блоке операций являются вызовы функций. Функция – это некоторая часть функциональности бота. Например, с помощью функций можно оперировать датой и временем, вычислять более сложные арифметические операции, преобразовывать строку текста в намерения, используя сервис NLU, работать с очередью сообщений клиента и т.д.
Чтобы вызвать функцию, нужно указать её имя, затем в круглых скобках перечислить через запятую её параметры. Имена большинства функций состоят из двух частей, разделяемых точкой: названия модуля и названия функции.
$number = math.rand(5, 10) // Получаем случайное число от 5 до 10. math – название модуля, rand – название функции
Также как и в случае методов объектов имена функций могут динамически вычисляться в процессе выполнения сценария бота.
$funcIdx = math.rand(0, 1) // Получаем случайное число 0 или 1, которое будет индексом названия функции в кортеже. $number = math.(('min', 'max').get($funcIdx))(3, 7) // Получаем название функции min или max и далее вызываем её. Таким образом, мы вычисляем случайным образом либо минимальное, либо максимальное значение.
1 комментарий
Анонимный
15 нояб., 2022массив нельзя называть как "ram", видимо это системная переменная