Save 37% off PRO during our Black Friday Sale! »

Kotlin DSL under an hour (v. 2021.10)

Kotlin DSL under an hour (v. 2021.10)

1bc80e2eee2adeaa8bb577798d92e9d0?s=128

Anton Arhipov

October 07, 2021
Tweet

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 {