Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Kotlin DSL in under an hour, DevoxxUK 2023

Kotlin DSL in under an hour, DevoxxUK 2023

Anton Arhipov

May 09, 2023
Tweet

More Decks by Anton Arhipov

Other Decks in Programming

Transcript

  1. Exposed https://github.com/JetBrains/Exposed object Cities : Table() { val id =

    integer("id").autoIncrement().primaryKey() // Column<Int> val name = varchar("name", 50) // Column<String> }
  2. 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]}") } }
  3. 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) {}
  4. fun main() { embeddedServer(Netty, port = 8080, host = “0.0.0.0",

    module = Application :: module).start(wait = true) } fun Application.main() { install(DefaultHeaders) install(CallLogging) routing { get("/") { call.respondHtml { head { title { +"Ktor App" } } body { p { +"Hello from Ktor!" } Ktor + kotlinx.html
  5. fun main() { embeddedServer(Netty, port = 8080, host = “0.0.0.0",

    module = Application :: module).start(wait = true) } fun Application.main() { install(DefaultHeaders) install(CallLogging) routing { get("/") { call.respondHtml { head { title { +"Ktor App" } } body { p { +"Hello from Ktor!" } Ktor + kotlinx.html
  6. fun main() { embeddedServer(Netty, port = 8080, host = “0.0.0.0",

    module = Application :: module).start(wait = true) } fun Application.main() { install(DefaultHeaders) install(CallLogging) routing { get("/") { call.respondHtml { head { title { +"Ktor App" } } body { p { +"Hello from Ktor!" } Ktor + kotlinx.html
  7. +

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

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

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

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

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

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

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

    = quux { corge = Blah() } } }
  15. 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)
  16. //extension property val Client.consoleString: String get() = "${twitter.handle} ${company.name}" //extension

    method fun Client.toConsoleString(): String { return "${twitter.handle} ${company.name}" }
  17. 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 functions
  18. 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) }
  19. context(DateContext) @DateDsl infix fun Int.March(n: Int): LD = LD.of(n, Month.MARCH,

    this) class DateContext Context object Context requirement
  20. context(DateContext) @DateDsl infix fun Int.March(n: Int): LD = LD.of(n, Month.MARCH,

    this) class DateContext fun client(block: context(DateContext) ClientBuilder.() - > Unit): Client { val builder = ClientBuilder() with(DateContext()) { block(builder) } return builder.build() } Context object Context requirement Context requirement Context scope
  21. context(DateContext) @DateDsl infix fun Int.March(n: Int): LD = LD.of(n, Month.MARCH,

    this) class DateContext val client = client { // .. . dob = 24 March 2000 } 24 March 2000 fun client(block: context(DateContext) ClientBuilder.() - > Unit): Client { val builder = ClientBuilder() with(DateContext()) { block(builder) } return builder.build() } Context object Context requirement Context requirement Context scope The function is available in the context scope The function is not available, missing DateContext
  22. kotlin { youtube = "youtube.com/kotlin" slack = "slack.kotl.in" } me

    { name = "Anton Arhipov" twitter = "@antonarhipov" slides = speakerdeck.com/antonarhipov code = github.com/antonarhipov }