Sobes.tech
Middle+

Čo sú doménovo špecifické jazyky (DSL) a ako ich vytvoriť v Kotlin?

sobes.tech AI

Odpoveď od AI

DSL (Domain Specific Language) je mali jezik, specijaliziran za конкретну област или задаћу, за разлику од језика опште намјене (GPL - General Purpose Language). Он омогућава изражавање рјешења проблема у терминима те области, чинећи код читљивијим, разумљивијим и изражајнијим за стручњаке у тој области.

Kotlin је погодан за креирање унутрашњих DSL-ова захваљујући подршци за такве могућности као што су:

  • Lambda изрази са receiver-ом: Омогућава дефинисање блокова кода који се извршавају у контексту одређеног објекта, што олакшава креирање хијерархијских структура и конфигурација.
  • Проширења (extension functions): Омогућавају додавање нових функција постојећим класама без њиховог мењања, што је згодно за проширење функционалности стандардних или страних класа за коришћење у DSL-овима.
  • Infix функције: Омогућавају позивање функција без тачке и заграда, што чини код сличнијим природном језику.
  • Оператори: Могуће је преоптерећење оператора (+, *, [] итд.) за креирање изражајнијег синтакса.
  • Користећи invoke оператор: Омогућава позивање објекта као функције, што може бити корисно за креирање градитеља или конфигуратора.
  • Тип-сигурни градитељи (type-safe builders): Комбинација lambda израза са receiver-ом и проширења, омогућава креирање структурираног и тип-сигурног API-ја.

Пример креирања једноставног DSL-а за изградњу HTML-а:

import kotlinx.html.*
import kotlinx.html.stream.appendHTML
import java.io.StringWriter

fun html(block: HTML.() -> Unit): String {
    val writer = StringWriter()
    writer.appendHTML().html(block)
    return writer.toString()
}

fun body(block: BODY.() -> Unit) {
    BLOCK.BODY()(block)
}

fun p(text: String) {
    BLOCK.P() {
        +text
    }
}

Користећи овај DSL:

fun main() {
    val result = html {
        body {
            p("Здраво, свет!")
            p("Ово је мој први DSL.")
        }
    }
    println(result)
}

Резултат извршавања:

<html><body><p>Здраво, свет!</p><p>Ово је мој први DSL.</p></body></html>

Овде lambda block: HTML.() -> Unit се извршава у контексту објекта HTML, омогућавајући директно позивање метода body. Функција p додаје параграф са текстом користећи унарни плус (+), који је преоптерећени оператор.