$30 off During Our Annual Pro Sale. View Details »

Kotlin DSL under an hour (v. 2021.10)

Kotlin DSL under an hour (v. 2021.10)

Anton Arhipov

October 07, 2021
Tweet

More Decks by Anton Arhipov

Other Decks in Programming

Transcript

  1. Kotlin DSL in under an hour @antonarhipov

  2. Why Kotlin?

  3. Null-safety Coroutines Multiplatform Syntax Why Kotlin?

  4. Null-safety Coroutines Multiplatform Syntax Why Kotlin?

  5. Null-safety Coroutines Multiplatform Syntax Why Kotlin?

  6. Null-safety Coroutines Multiplatform Syntax Why Kotlin?

  7. Null-safety Coroutines Multiplatform Syntax Why Kotlin? DSL

  8. Domain-speci fi c, i.e.

  9. tailored for the speci fi c task Domain-speci fi c,

    i.e.
  10. External

  11. External VS Internal

  12. External VS Internal

  13. External VS Internal

  14. External VS Internal

  15. External VS Internal

  16. Internal

  17. createHTML().html { head { +"Hello!" } body { ul {

    p { +"This is my awesome text!" } } } } kotlinx.html https://github.com/Kotlin/kotlinx.html
  18. Exposed https://github.com/JetBrains/Exposed object Cities : Table() { val id =

    integer("id").autoIncrement().primaryKey() // Column<Int> val name = varchar("name", 50) // Column<String> }
  19. Exposed https://github.com/JetBrains/Exposed object Cities : Table() { val id =

    integer("id").autoIncrement().primaryKey() // Column<Int> val name = varchar("name", 50) // Column<String> } transaction { create (Cities) val tallinnId = Cities.insert { it[name] = "Tallinn" } get Cities.id for (city in Cities.selectAll()) { println("${city[Cities.id]}: ${city[Cities.name]}") } }
  20. Kotlin DSL in TeamCity project { vcsRoot(ApplicationVcs) buildType { id("Application")

    name = "Application" vcs { root(ApplicationVcs) } artifactRules = "target/*jar" steps { maven { goals = "clean package" } } triggers { vcs {} } dependencies { snapshot(Library) {}
  21. fun main(args: Array<String>) { embeddedServer(Jetty, commandLineEnvironment(args)).start(wait = true) } fun

    Application.main() { install(DefaultHeaders) install(CallLogging) routing { get("/") { call.respondHtml { head { title { +"Ktor App" } } body { p { +"Hello from Ktor!" } } Ktor
  22. fun main(args: Array<String>) { embeddedServer(Jetty, commandLineEnvironment(args)).start(wait = true) } fun

    Application.main() { install(DefaultHeaders) install(CallLogging) routing { get("/") { call.respondHtml { head { title { +"Ktor App" } } body { p { +"Hello from Ktor!" } } Ktor
  23. fun main(args: Array<String>) { embeddedServer(Jetty, commandLineEnvironment(args)).start(wait = true) } fun

    Application.main() { install(DefaultHeaders) install(CallLogging) routing { get("/") { call.respondHtml { head { title { +"Ktor App" } } body { p { +"Hello from Ktor!" } } Ktor
  24. They all look similar!

  25. foo { bar { baz = "Hello!" qux = quux

    { corge = "Blah" } } }
  26. foo { bar { baz = "Hello!" qux = quux

    { corge = "Blah" } } }
  27. foo { bar { baz = "Hello!" qux = quux

    { corge = "Blah" } } }
  28. foo { bar { baz = "Hello!" qux = quux

    { corge = "Blah" } } }
  29. foo { bar(grault = 1) { baz = "Hello!" qux

    = quux { corge = "Blah" } } }
  30. foo { bar(grault = 1) { baz = "Hello!" qux

    = quux { corge = Blah() } } }
  31. foo { bar(grault = 1) { baz = "Hello!" qux

    = quux { corge = Blah() } } }
  32. Let’s write some code! https://github.com/antonarhipov/kotlin-dsl-examples

  33. Let’s write some code! https://github.com/antonarhipov/kotlin-dsl-examples

  34. Type-safe builders https://kotlinlang.org/docs/reference/type-safe-builders.html

  35. final ClientBuilder builder = new ClientBuilder(); builder.setFirstName("Anton"); builder.setLastName("Arhipov"); final TwitterBuilder

    twitterBuilder = new TwitterBuilder(); twitterBuilder.setHandle("@antonarhipov"); builder.setTwitter(twitterBuilder.build()); final CompanyBuilder companyBuilder = new CompanyBuilder(); companyBuilder.setName("JetBrains"); companyBuilder.setCity("Tallinn"); builder.setCompany(companyBuilder.build()); final Client client = builder.build(); System.out.println("Created client is: " + client); val client = createClient { firstName = "Anton" lastName = "Arhipov" twitter { handle = "@antonarhipov" } company { name = "JetBrains" city = "Tallinn" } } println("Created client is: " + client.consoleString)
  36. //extension property val Client.consoleString: String get() = "${twitter.handle} ${company.name}" //extension

    method fun Client.toConsoleString(): String { return "${twitter.handle} ${company.name}" }
  37. fun createClient(c: ClientBuilder.() -> Unit): Client { val builder =

    ClientBuilder() c(builder) return builder.build() } fun ClientBuilder.company(t: CompanyBuilder.() -> Unit) { company = CompanyBuilder().apply(t).build() } fun ClientBuilder.twitter(t: CompanyBuilder.() -> Unit) { twitter = TwitterBuilder().apply(t).build() } Lambda with receiver Extension methods
  38. twitter { handle = "@antonarhipov" company { name = "JetBrains"

    city = "Tallinn" } } @DslMarker annotation class ClientDsl @ClientDsl class CompanyBuilderDsl : CompanyBuilder() @ClientDsl class TwitterBuilderDsl : TwitterBuilder() twitter { handle = "@antonarhipov" company { name = "JetBrains" city = "Tallinn" } } Scope control
  39. In fi x notation https://kotlinlang.org/docs/reference/functions.html

  40. dateTime = LocalDateTime.of(2018, Month.DECEMBER, 11, 0, 0) dateTime = 11

    December 2018 at (14 hh 0) infix fun Int.December(n: Int) : LocalDate { return LocalDate.of(n, Month.DECEMBER, this) } infix fun LocalDate.at(n: Pair<Int, Int>): LocalDateTime { return this.atTime(n.first, n.second) } infix fun Int.hh(n: Int): Pair<Int, Int> { return Pair(this, n) }
  41. T.() -> Unit

  42. Kotlin { YouTube = "youtube.com/kotlin" Slack = "slack.kotl.in" } me

    { name = "Anton Arhipov" twitter = "@antonarhipov" slides = speakerdeck.com/antonarhipov } books { courses {