15. Выражения и шаблоны

Две вкладки окна аргумента, в которых значение не берётся готовым, а вычисляется. Язык вычислений — серверный: редактор его подсвечивает и проверяет, но не исполняет (Выражение, Функция).

Редактор выражения

Редактор выражений с деревом функций
Figure 1. Вкладка «Выражение»

Слева — сам текст выражения с подсветкой: строки, числа, имена функций и переменные окрашены по-разному. Справа — дерево того, что можно использовать.

Имя переменной пишется в квадратных скобках: [dtmf], [sitedomain]. Строки — в двойных кавычках. Всё остальное — функции и операторы.

Одинарные кавычки — не замена двойным. Синтаксис языка в основе своей эрланговский, и текст в одинарных кавычках становится атомом. Атомы на сервере ограничены и по количеству, и по длине: короткая строка пройдёт, а большой JSON в одинарных кавычках разместить не удастся.

Правило простое: строки — только в двойных кавычках.

Дерево функций

Дерево функций
Figure 2. Раскрытая группа функций

Дерево устроено по разделам: переменные этого сценария, общие функции по темам (математика, строки, дата и время, преобразования, хеши, файлы, доступ), константы и символы, функции конкретного вида сценария.

Рядом с каждой группой — сколько в ней функций. У каждой функции показаны имя и типы параметров: substr (str,int,int). Клик вставляет вызов в текст на место курсора.

Поле над деревом ищет по имени — быстрее, чем раскрывать группы подряд.

Переменные сценария лежат в дереве первым разделом. Вставлять их оттуда надёжнее, чем печатать руками: имя подставится ровно так, как оно записано, вместе со скобками.

Переменная без значения

[имя] — не подстановка текста, а обращение к переменной: сервер заменяет запись вызовом функции доступа по идентификатору. Если значения у переменной нет, этот вызов бросает исключение — выражение не возвращает ложь, оно падает целиком.

Отсюда следствие, о котором стоит знать заранее: сравнить переменную с «ничем» нельзя. [x] == null не работает, потому что до сравнения дело не доходит — падает уже [x].

Наличие значения проверяет отдельная функция, и берёт она имя переменной строкой, а не саму переменную:

check_variable("x")

Истина — если переменная с таким именем существует и содержит значение. Имя здесь пишется строкой в двойных кавычках, а не в квадратных скобках: скобки как раз и означали бы обращение к значению, ради которого всё и затевалось.

В том же семействе есть ещё две функции, которые часто избавляют от проверки вовсе:

  • get_variable_value("x", "") — значение переменной, а если значения нет, второй аргумент. Выражение не падает: вместо исключения возвращается умолчание.

  • set_variable_value_if_undefined("x", "") — задаёт переменной значение, если его ещё нет; заданное не трогает. Одна такая строка в начале избавляет от проверок во всех выражениях после неё.

На практике это встречается реже, чем можно подумать. Компонент Старт по умолчанию заводит переменные с пустыми значениями их типов — ровно для того, чтобы выражения не падали. Проверка нужна там, где это поведение изменено настройкой компонента.

Шаблон

Редактор шаблонов
Figure 3. Вкладка «Шаблон»

Шаблон — это обычный текст, в котором участки в двойных фигурных скобках вычисляются как выражения:

Здравствуйте, {{ str([name]) }}. Ваш баланс {{ str([sum]) }} рублей.

Подсветка отделяет подстановки от остального текста, так что забытая скобка видна сразу.

Выражение и шаблон взаимно переводятся: переключив вкладку, вы увидите то же самое значение в другой записи. Перевод делает сервер, а не редактор.

Две записи шаблона

Двойные скобки — нынешняя запись. Раньше подстановку писали одинарными, и сервер по-прежнему её понимает. Различает он их по одному признаку: есть ли в шаблоне хотя бы одна двойная открывающая скобка.

В шаблоне Как сервер читает фигурные скобки

Двойных скобок нет

Каждая одинарная { … } — подстановка, содержимое вычисляется как выражение

Двойные скобки есть

Подстановка только {{ … }}, одинарные скобки — обычный текст

Из этого следует правило, которое стоит запомнить: фигурные скобки в тексте безопасны только тогда, когда в шаблоне есть двойные. Скажем, тело запроса в формате JSON

{ "code": 200, "text": "готово" }

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

Пометка формата

Чтобы скобки остались текстом, в начало шаблона добавляется пустая подстановка:

{{}}{ "code": 200, "text": "готово" }

Она ничего не подставляет и в результат не попадает — её единственное дело объявить формат. Тело шаблона при этом не меняется, и его можно копировать в документацию и обратно как есть.

Ставить пометку руками не нужно: редактор сам предложит её, как только увидит скобки, которые сервер прочитает не так, как вы задумали.

Появляется она не всегда, а только когда объявлять формат больше нечем: если в шаблоне уже есть подстановка {{ … }}, формат объявлен ею, а если фигурных скобок нет вовсе — объявлять нечего. Поэтому в обычном шаблоне с подстановками пометки вы не увидите.

Что делает редактор

Ничего не делает молча. Увидев шаблон, который сервер прочитает не так, как он выглядит, редактор показывает полосу над полем.

Полоса состояния формата шаблона
Figure 4. Полоса над полем: скобки JSON сервер прочитает подстановкой

Полоса объясняет положение и предлагает правку, но сама текст не трогает. Она держится, пока держится причина, и гаснет, как только шаблон исправлен — в том числе если вы поправили его руками. Полос две:

  • жёлтая — формат непоследователен или сервер откажется разбирать шаблон;

  • спокойная — шаблон в старой записи, но исправен: сервер выполнит его как есть, а перевести в новую запись можно, когда будет удобно.

Окно с разницей
Figure 5. Окно «Формат шаблона»

Кнопка полосы открывает окно «Формат шаблона»: слева шаблон, каким он сейчас, справа — каким станет, оба тела копируются. Под ними — итог проверки. Там, где правка обещает сохранить смысл (перевод старой записи в новую), редактор это доказывает: он повторяет у себя серверный разбор и сверяет, что из обоих шаблонов получается одно и то же выражение.

Отменить возвращает к правке, ничего не изменив. Применить выполняет правку — одним шагом, который отменяется обычным CTRL + Z.

Если вы нажали Сохранить, а жёлтая полоса на экране, окно откроется само и добавит третью кнопку — Оставить как есть. Сохранить шаблон нетронутым можно всегда: последнее слово за вами.

В этом окне появляется и флажок «Так же поступить с остальными шаблонами сценария». Он снят по умолчанию, и это осознанно: правку лучше делать там, где вы её видите. Ставьте его, когда одно и то же исправление приходится подтверждать в каждом компоненте.

Экранирование скобок косой чертой — \{ и \} — работает в обеих записях, но в новой оно нужно ровно для одного: записать в тексте две скобки подряд. Одиночная скобка там и так остаётся текстом, и косые черты перед ней только мешают читать. Редактор их снимет сам, когда будет переводить шаблон.

Проверка на сервере

Свои правила разбора редактор не выдумывает: язык принадлежит серверу, и проверяет выражение он же.

Ошибка проверки выражения
Figure 6. Сервер вернул ошибку

Проверка идёт, когда вы уходите из поля, и ещё раз — при сохранении значения. Ошибка показывается так, как её сформулировал сервер: рамка поля краснеет, под ним появляется сообщение.

Что важно знать:

  • ошибка не запрещает сохранить. Редактор предупреждает, а не сторожит: бывает, что сервер отвечает не то, а работа стоять не должна;

  • при обрыве связи проверки нет. Ответ не пришёл — сообщение не показывается. Отсутствие ошибки при потерянной связи ничего не доказывает;

  • ответ запоминается. Открыв то же выражение снова, вы увидите уже известную ошибку без нового запроса.

Несколько действий в одном выражении

У языка эрланговский синтаксис, и операторы в нём разделяются запятыми. Значением выражения становится последний из них. Это открывает приём, о котором стоит знать заранее, — функцию component.

component выполняет прямо внутри выражения типизированный компонент сценария со свойствами, заполненными здесь же, в редакторе выражений, дожидается его завершения и передаёт управление следующему оператору. То есть кусок сценария можно записать не квадратами на карте, а последовательностью внутри одного аргумента.

Это глубокий приём, а не повседневный. Он уместен там, где рисовать на карте три квадрата ради одного технического шага дороже, чем написать строку, — и неуместен там, где логику потом придётся читать глазами: на карте она видна, внутри выражения нет.

Ограничения тоже есть: произвольные внешние методы эрланга из выражения не вызываются — для этого нужна отдельная настройка разрешений на сервере. Подробности — Выражение и Функция.

Что стоит помнить

  • Выражение всегда возвращает одно значение. Ветвление делается компонентами на карте, а не формулой.

  • Приведение типов явное: str(…​) для строки, num(…​) для числа. Молчаливого приведения не будет.

  • Переменная без значения роняет выражение, а не даёт ложь: [x] == null не работает. Проверяйте check_variable("x") или берите значение с умолчанием — get_variable_value("x", "").

  • Длинное выражение — повод завести переменную и разбить вычисление на два шага. Читать сценарий будете вы же.

◀ 14. Аргумент

16. Меню и переводы ▶