Вот и пришла пора для заключительной статьи в основном цикле о Kotlin. Что это значит? Пользуясь знаниями из предыдущих статей (Введение, Незнакомые конструкции, Мигрируем из Java, Неловкие моменты) ниже мы с вами напишем собственный DSL (domain-specific language), обсудим что это такое и чем Kotlin, как язык, способствует написанию предметно-ориентированных языков, а также как это упрощает разработчикам жизнь, я расскажу о собственном опыте в разработке DSL и о проблемах, которые возникают. Статья может показаться довольно большой, так и есть, я постарался уместить в неё основной концентрат собственных знаний о построении DSL в Kotlin.

Что такое DSL?
Языки программирования можно разделить на 2 типа: универсальные языки (general-purpose programming language) и предметно-ориентированные (domain-specific language). Популярные примеры DSL это SQL или регулярные выражения. Язык уменьшает объем функциональности который, он дает, при этом он способен эффективно решать определенную проблему. В том числе это способ описать программу не в императивном стиле, когда вы говорите как нужно получить результат в универсальны языках, а в декларативном, когда вы говорите что вы хотите получить. Пусть у вас есть стандартный процесс выполнения, который иногда может меняться, дорабатываться, но в целом вы хотите подстраивать его под разные данные и формат результата. Создавая DSL вы делаете гибкий инструмент для решения различных задач из одной предметной области при этом не задумываетесь об оптимизации. Это некоторое API, виртуозно пользуясь которым, вы можете сильно упростить себе жизнь и долгосрочную поддержку системы.
«Чистое API»
«Чистым» называется API, которое требует минимальных действий для получения результата, никакой мишуры и фантиков. Давайте рассмотрим, что нам дает Kotlin для построения такого API.
На пути к совершенству
Давайте перечислим основные преимущества Kotlin, которые позволяют достаточно чисто писать на этом языке и доступны для построения собственного DSL. Ниже представлена табличка в которой перечислены основные улучшения синтаксиса языка, которые стоит использовать

Благодаря этим возможностям вы способны писать код чище, избавиться от множества вызовов методов и при этом сделать разработку еще более приятным занятием («куда уж приятнее?» — спросите вы). Мне понравилось сравнение из книжки, что в натуральных языках, например, в английском, предложения построены из слов и граматические правила управляют тем как нужно объединять слова друг с другом. Аналогично в DSL, одна операция может быть сложена из нескольких вызовов методов, а проверка типов обеспечит гарантию, что конструкция имеет смысл.
Оказывается, что довольно трудно совместить одновременно универсальный язык и DSL, стереть границу которая их разделяет. Прикрутить что-то к чему-то можно всегда, но как это сделать, чтобы работа с таким DSL была максимально простой и нативной? Давайте обсудим «внутренние DSL» и как они стирают интеграцию.
Внутренний DSL
Проще всего понять что такое «внутренний» DSL на примере. Вот у вас есть реляционная база данных и мы хотим выбрать из неё определенные записи, как мы это делаем? Очевидно, SQL. У нас будет select запрос в котором мы укажем что и как нужно достать. В перевес этому мы можем взять фреймворк Exposed на Kotlin (не то чтобы я сторонник миллионов оберток, но это хороший пример). Exposed — это работа с базой данных в sql подобном стиле прямо из кода. Больше подробностей по фреймворку по ссылке в конце статьи.
Пример DSL
Предлагаю посмотреть, а ради чего всё это. Я приведу пример из практики. Библиотека Clabo для создания телеграм ботов в декларативном стиле, демонстрирует возможности, которые дает Kotlin для построения DSL. Каждый бот имеет свой ключик, который выдается при создании бота для у