15. Выражения и шаблоны
Редактор выражения
Слева — сам текст выражения с подсветкой: строки, числа, имена функций и переменные окрашены по-разному. Справа — дерево того, что можно использовать.
Имя переменной пишется в квадратных скобках: [dtmf], [sitedomain].
Строки — в двойных кавычках. Всё остальное — функции и операторы.
|
Одинарные кавычки — не замена двойным. Синтаксис языка в основе своей эрланговский, и текст в одинарных кавычках становится атомом. Атомы на сервере ограничены и по количеству, и по длине: короткая строка пройдёт, а большой JSON в одинарных кавычках разместить не удастся. Правило простое: строки — только в двойных кавычках. |
Дерево функций
Дерево устроено по разделам: переменные этого сценария, общие функции по темам (математика, строки, дата и время, преобразования, хеши, файлы, доступ), константы и символы, функции конкретного вида сценария.
Рядом с каждой группой — сколько в ней функций. У каждой функции показаны
имя и типы параметров: substr (str,int,int). Клик вставляет вызов
в текст на место курсора.
Поле над деревом ищет по имени — быстрее, чем раскрывать группы подряд.
|
Переменные сценария лежат в дереве первым разделом. Вставлять их оттуда надёжнее, чем печатать руками: имя подставится ровно так, как оно записано, вместе со скобками. |
Переменная без значения
[имя] — не подстановка текста, а обращение к переменной: сервер заменяет
запись вызовом функции доступа по идентификатору. Если значения у переменной
нет, этот вызов бросает исключение — выражение не возвращает ложь,
оно падает целиком.
Отсюда следствие, о котором стоит знать заранее: сравнить переменную
с «ничем» нельзя. [x] == null не работает, потому что до сравнения дело
не доходит — падает уже [x].
Наличие значения проверяет отдельная функция, и берёт она имя переменной строкой, а не саму переменную:
check_variable("x")
Истина — если переменная с таким именем существует и содержит значение. Имя здесь пишется строкой в двойных кавычках, а не в квадратных скобках: скобки как раз и означали бы обращение к значению, ради которого всё и затевалось.
В том же семействе есть ещё две функции, которые часто избавляют от проверки вовсе:
-
get_variable_value("x", "")— значение переменной, а если значения нет, второй аргумент. Выражение не падает: вместо исключения возвращается умолчание. -
set_variable_value_if_undefined("x", "")— задаёт переменной значение, если его ещё нет; заданное не трогает. Одна такая строка в начале избавляет от проверок во всех выражениях после неё.
|
На практике это встречается реже, чем можно подумать. Компонент Старт по умолчанию заводит переменные с пустыми значениями их типов — ровно для того, чтобы выражения не падали. Проверка нужна там, где это поведение изменено настройкой компонента. |
Шаблон
Шаблон — это обычный текст, в котором участки в двойных фигурных скобках вычисляются как выражения:
Здравствуйте, {{ str([name]) }}. Ваш баланс {{ str([sum]) }} рублей.
Подсветка отделяет подстановки от остального текста, так что забытая скобка видна сразу.
Выражение и шаблон взаимно переводятся: переключив вкладку, вы увидите то же самое значение в другой записи. Перевод делает сервер, а не редактор.
Две записи шаблона
Двойные скобки — нынешняя запись. Раньше подстановку писали одинарными, и сервер по-прежнему её понимает. Различает он их по одному признаку: есть ли в шаблоне хотя бы одна двойная открывающая скобка.
| В шаблоне | Как сервер читает фигурные скобки |
|---|---|
Двойных скобок нет |
Каждая одинарная { … } — подстановка, содержимое вычисляется как выражение |
Двойные скобки есть |
Подстановка только {{ … }}, одинарные скобки — обычный текст |
Из этого следует правило, которое стоит запомнить: фигурные скобки в тексте безопасны только тогда, когда в шаблоне есть двойные. Скажем, тело запроса в формате JSON
{ "code": 200, "text": "готово" }
в шаблоне без двойных скобок сервер прочитает как подстановку и попробует вычислить его содержимое — а выражением оно не является.
Пометка формата
Чтобы скобки остались текстом, в начало шаблона добавляется пустая подстановка:
{{}}{ "code": 200, "text": "готово" }
Она ничего не подставляет и в результат не попадает — её единственное дело объявить формат. Тело шаблона при этом не меняется, и его можно копировать в документацию и обратно как есть.
Ставить пометку руками не нужно: редактор сам предложит её, как только увидит скобки, которые сервер прочитает не так, как вы задумали.
Появляется она не всегда, а только когда объявлять формат больше нечем:
если в шаблоне уже есть подстановка {{ … }}, формат объявлен ею, а если
фигурных скобок нет вовсе — объявлять нечего. Поэтому в обычном шаблоне
с подстановками пометки вы не увидите.
Что делает редактор
Ничего не делает молча. Увидев шаблон, который сервер прочитает не так, как он выглядит, редактор показывает полосу над полем.
Полоса объясняет положение и предлагает правку, но сама текст не трогает. Она держится, пока держится причина, и гаснет, как только шаблон исправлен — в том числе если вы поправили его руками. Полос две:
-
жёлтая — формат непоследователен или сервер откажется разбирать шаблон;
-
спокойная — шаблон в старой записи, но исправен: сервер выполнит его как есть, а перевести в новую запись можно, когда будет удобно.
Кнопка полосы открывает окно «Формат шаблона»: слева шаблон, каким он сейчас, справа — каким станет, оба тела копируются. Под ними — итог проверки. Там, где правка обещает сохранить смысл (перевод старой записи в новую), редактор это доказывает: он повторяет у себя серверный разбор и сверяет, что из обоих шаблонов получается одно и то же выражение.
Отменить возвращает к правке, ничего не изменив. Применить выполняет правку — одним шагом, который отменяется обычным CTRL + Z.
|
Если вы нажали Сохранить, а жёлтая полоса на экране, окно откроется само и добавит третью кнопку — Оставить как есть. Сохранить шаблон нетронутым можно всегда: последнее слово за вами. В этом окне появляется и флажок «Так же поступить с остальными шаблонами сценария». Он снят по умолчанию, и это осознанно: правку лучше делать там, где вы её видите. Ставьте его, когда одно и то же исправление приходится подтверждать в каждом компоненте. |
|
Экранирование скобок косой чертой — \{ и \} — работает в обеих записях, но в новой оно нужно ровно для одного: записать в тексте две скобки подряд. Одиночная скобка там и так остаётся текстом, и косые черты перед ней только мешают читать. Редактор их снимет сам, когда будет переводить шаблон. |
Проверка на сервере
Свои правила разбора редактор не выдумывает: язык принадлежит серверу, и проверяет выражение он же.
Проверка идёт, когда вы уходите из поля, и ещё раз — при сохранении значения. Ошибка показывается так, как её сформулировал сервер: рамка поля краснеет, под ним появляется сообщение.
Что важно знать:
-
ошибка не запрещает сохранить. Редактор предупреждает, а не сторожит: бывает, что сервер отвечает не то, а работа стоять не должна;
-
при обрыве связи проверки нет. Ответ не пришёл — сообщение не показывается. Отсутствие ошибки при потерянной связи ничего не доказывает;
-
ответ запоминается. Открыв то же выражение снова, вы увидите уже известную ошибку без нового запроса.
Несколько действий в одном выражении
У языка эрланговский синтаксис, и операторы в нём разделяются запятыми.
Значением выражения становится последний из них. Это открывает приём,
о котором стоит знать заранее, — функцию component.
component выполняет прямо внутри выражения типизированный компонент
сценария со свойствами, заполненными здесь же, в редакторе выражений,
дожидается его завершения и передаёт управление следующему оператору.
То есть кусок сценария можно записать не квадратами на карте,
а последовательностью внутри одного аргумента.
|
Это глубокий приём, а не повседневный. Он уместен там, где рисовать на карте три квадрата ради одного технического шага дороже, чем написать строку, — и неуместен там, где логику потом придётся читать глазами: на карте она видна, внутри выражения нет. |
Что стоит помнить
-
Выражение всегда возвращает одно значение. Ветвление делается компонентами на карте, а не формулой.
-
Приведение типов явное:
str(…)для строки,num(…)для числа. Молчаливого приведения не будет. -
Переменная без значения роняет выражение, а не даёт ложь:
[x] == nullне работает. Проверяйтеcheck_variable("x")или берите значение с умолчанием —get_variable_value("x", ""). -
Длинное выражение — повод завести переменную и разбить вычисление на два шага. Читать сценарий будете вы же.