Slide 1

Slide 1 text

Kotlin DSL
 in under an hour @antonarhipov Prague, 18-19 October 2018

Slide 2

Slide 2 text

DSL another Yet talk

Slide 3

Slide 3 text

DSL wat??

Slide 4

Slide 4 text

External DSL

Slide 5

Slide 5 text

Internal DSL

Slide 6

Slide 6 text

createHTML().html { head { +"Hello!" } body { ul { p { +"This is my awesome text!" } } } } kotlinx.html https://github.com/Kotlin/kotlinx.html

Slide 7

Slide 7 text

Anko https://github.com/Kotlin/anko verticalLayout { padding = dip(30) val name = editText { hint = "Name" textSize = 24f } val pwd = editText { hint = "Password" textSize = 24f button("Login") { textSize = 26f onClick { toast("Hello, ${name.text}!") } }

Slide 8

Slide 8 text

Gradle Kotlin DSL https://github.com/gradle/kotlin-dsl plugins { java kotlin("jvm") version "1.2.70" } group = "org.arhan" version = "1.0-SNAPSHOT" repositories { maven { setUrl("http://dl.bintray.com/kotlin/kotlin-eap") } jcenter() } dependencies { val kotlinx_html_version = "0.6.11" compile(kotlin("stdlib-jdk8")) compile("org.jetbrains.kotlinx:kotlinx-html-jvm:${kotlinx_html_version}") testCompile("junit", "junit", "4.12")

Slide 9

Slide 9 text

Exposed https://github.com/JetBrains/Exposed object Cities : Table() { val id = integer("id").autoIncrement().primaryKey() // Column val name = varchar("name", 50) // Column } 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]}") } }

Slide 10

Slide 10 text

https://github.com/nfrankel/kaadin Kaadin theme = "valo" verticalLayout(margin = true, spacing = true) { tabSheet { tab("Interactions") { accordion { tab("Button", HAND_O_RIGHT) { horizontalLayout(true, true) { button() button("Label") button("Label", HAND_O_RIGHT) button("Click me", onClick = { show("Clicked") }) button("Click me", HAND_O_RIGHT, { show("Clicked") }) } }

Slide 11

Slide 11 text

k8s-kotlin-dsl https://github.com/fkorotkov/k8s-kotlin-dsl val client = DefaultKubernetesClient().inNamespace("default") client.extensions().ingresses().createOrReplace( newIngress { metadata { name = "example-ingress" } spec { backend { serviceName = "example-service" servicePort = IntOrString(8080) } } } )

Slide 12

Slide 12 text

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) {}

Slide 13

Slide 13 text

fun main(args: Array) { 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

Slide 14

Slide 14 text

They all look similar

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

Let’s write some code! https://github.com/jonnyzzz/kotlin-dsl-demo

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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)

Slide 25

Slide 25 text

//extension property val Client.consoleString: String get() = "${twitter.handle} ${company.name}" //extension method fun Client.toConsoleString(): String { return "${twitter.handle} ${company.name}" }

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

Infix notation https://kotlinlang.org/docs/reference/functions.html

Slide 29

Slide 29 text

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): LocalDateTime { return this.atTime(n.first, n.second) } infix fun Int.hh(n: Int): Pair { return Pair(this, n) }

Slide 30

Slide 30 text

T.() -> Unit

Slide 31

Slide 31 text

me { name = "Anton Arhipov" twitter = "@antonarhipov" } books { courses { Kotlin { Try = "try.kotlinlang.org" Slack = "slack.kotl.in" }