SlideShare une entreprise Scribd logo
1  sur  85
Télécharger pour lire hors ligne
DSLs IN A
KOTLIN WAY
Ubiratan Soares
July / 2018
VERSION
2.0
SELECT *
FROM accounts
WHERE id=12345
SELECT *
FROM accounts
WHERE id=12345
"
"
String sql = SQLiteQueryBuilder
.select("*")
.from("accounts")
.where("id=12345")
.toString();
https://github.com/alexfu/SQLiteQueryBuilder
<!DOCTYPE html>
<html>
<body>
<h1>Hey!!"h1>
<div>Ho!<span>Lets go!!"span>
!"div>
!"body>
!"html>
val tree = createHTMLDocument().html {
body {
h1 { +"Hey" }
div {
+"Ho!" span { +"Lets go!" }
}
}
}
https://github.com/Kotlin/kotlinx.html
Disclaimer : Strategic jump
Type Aliases
Sealed Classes
Extension Functions
Extension Properties
ETC
VERSION
1.0
INFIX
NOTATION
class Extractor {
fun firstLetter(target: String) =
target[0].toString()
}
val k = Extractor().firstLetter("Kotlin")
class Extractor {
infix fun firstLetter(target: String) =
target[0].toString()
}
val k = Extractor() firstLetter "Kotlin"
👌
object extract {
infix fun firstLetterOf(target: String)
= target[0].toString()
}
object extract {
infix fun firstLetterOf(target: String)
= target[0].toString()
}
val first = extract firstLetterOf "Awesome"
object acronymn {
infix fun from(target: String) = Chainer(
initials = mutableListOf(),
seed = target
)
}
object acronymn {
infix fun from(target: String) = Chainer(
initials = mutableListOf(),
seed = target
)
}
class Chainer(
private val initials: MutableList<String>,
seed: String) {
init {
initials += seed.first().toString()
}
class Chainer(…) {
init {
initials += seed.first().toString()
}
infix fun and(another: String) =
Chainer(initials, another)
class Chainer(…) {
init {
initials += seed.first().toString()
}
infix fun and(another: String) =
Chainer(initials, another)
sealed class Joiner
object noPunctuaction : Joiner()
object dots : Joiner()
class Chainer(…) {
infix fun joinedWith(option: Joiner) =
initials.reduce { previous, letter !"
val next = when (option) {
is noPunctuaction !" letter
is dots !" "$letter."
}
"$previous$next"
}
class Chainer(…) {
infix fun joinedWith(option: Joiner) =
initials.reduce { previous, letter !"
val next = when (option) {
is noPunctuaction !" letter
is dots !" "$letter."
}
"$previous$next"
}
class Chainer(…) {
infix fun joinedWith(option: Joiner) =
initials.reduce { previous, letter !"
val next = when (option) {
is noPunctuaction !" letter
is dots !" "$letter."
}
"$previous$next"
}
class Chainer(…) {
infix fun joinedWith(option: Joiner) =
initials.reduce { previous, letter !"
val next = when (option) {
is noPunctuaction !" letter
is dots !" "$letter."
}
"$previous$next"
}
val dsl = acronymn from
"Domain" and
"Specific" and
"Language" joinedWith
noPunctuaction //DSL
val dsl = acronymn from
"Domain" and
"Specific" and
"Language" joinedWith
dots //D.S.L
OPERATOR
OVERLOADS
val items = mutableListOf(1, 2, 3)
items += 4
val items = mutableListOf(1, 2, 3)
items += 4
/#$
* Adds the specified [element] to this mutable collection.
%&
@kotlin.internal.InlineOnly
public inline operator fun <T> MutableCollection<in T>.plusAssign(element: T) {
this.add(element)
}
typealias IntPair = Pair<Int, Int>
val calendar by lazy {
Calendar.getInstance()
}
operator fun Date.plus(args: IntPair): Date {
calendar.time = this
calendar.add(args.first, args.second)
return calendar.time
}
operator fun Date.minus(args: IntPair): Date {
calendar.time = this
calendar.add(args.first, -args.second)
return calendar.time
}
operator fun Date.plus(args: IntPair): Date {
calendar.time = this
calendar.add(args.first, args.second)
return calendar.time
}
operator fun Date.minus(args: IntPair): Date {
calendar.time = this
calendar.add(args.first, -args.second)
return calendar.time
}
fun Int.days() =
Calendar.DAY_OF_YEAR to this
fun Int.months() =
Calendar.MONTH to this
val atPast = Date() - 2.months()
val atFuture = Date() + 15.days()
val past = Date() - 2.months
val future = Date() + 15.days
👌
val Int.days: IntPair
get() = Calendar.DAY_OF_YEAR to this
val Int.months: IntPair
get() = Calendar.MONTH to this
A The problem
like with spannables
on Android
val toSpan = SpannableStringBuilder()
val start = toSpan.length
toSpan.append("First Part")
toSpan.setSpan(
UnderlineSpan(),
start,
toSpan.length,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
toSpan.setSpan(
StyleSpan(android.graphics.Typeface.BOLD),
start,
toSpan.length,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
toSpan.append("not bold or underlined")
operator fun SpannableString.plus(s: String) =
SpannableString(TextUtils.concat(this, s))
operator fun SpannableString.plus(s: SpannableString) =
SpannableString(TextUtils.concat(this, s))
fun span(given: CharSequence, span: Any): SpannableString {
val spannable =
if (given is String) SpannableString(given)
else given as? SpannableString ?: throw CannotBeSpanned
return spannable.apply {
setSpan(span, 0, length, SPAN_EXCLUSIVE_EXCLUSIVE)
}
}
object CannotBeSpanned : IllegalArgumentException(
"Cannot apply span. Should be String or SpannableString"
)
// Add more hooks to same span() function
fun italic(given: CharSequence) =
span(given, StyleSpan(Typeface.ITALIC))
fun underline(given: CharSequence) =
span(given, UnderlineSpan())
fun bold(given: CharSequence) =
span(given, StyleSpan(Typeface.BOLD))
val spanned =
"normal" +
bold("bold") +
italic("italic")
label.setText(spanned)
LAMBDAS +
RECEIVERS
fun x(lambda: () !" Unit) { lambda() }
fun y(lambda: () !" Int) = lambda()
val x: () !" Int = { TODO() }
val result = x()
val add = fun(a: Int, b: Int) = a + b
fun calculate(func: (Int, Int) !" Int) {
func.invoke(2,2)
}
// Trailling Notation
calculate { a, b !" a + b }
// Normal notation
calculate(add)
class Receiver(val data: Int)
// Kotlin allows us to add an extension function
// literal to a type. Such lambda acquires the
// properties of non-static method in the context
val addOne: Receiver.() !" Int = {
data + 1
}
val two = addOne(Receiver(1))
val twoAgain = Receiver(1).addOne()
fun receive(block: Receiver.() !" Unit) {
val r = Receiver(data = 1)
block(r)
// r.block() is exactly the same
}
receive {
println(data) // 1
}
https://graphql.org/swapi-graphql/
val starWars = query {
allFilms {
film { title director }
}
}
println(starWars)
> query { allFilms { film { title director } } }
val starWars = query {
'( TODO
}
val starWars = query {
'( TODO
}
fun query(): String {
return "query { ${ '( Something here } }"
}
val starWars = query {
'( TODO
}
fun query(setup: AllFilmsBlock.() !" String) =
"query { ${setup(AllFilmsBlock())} }"
val starWars = query {
'( TODO
}
fun query(setup: AllFilmsBlock.() !" String) =
"query { ${setup(AllFilmsBlock())} }"
val starWars = query {
'( TODO
}
fun query(setup: AllFilmsBlock.() !" String) =
"query { ${setup(AllFilmsBlock())} }"
fun query(setup: AllFilmsBlock.() !" String) =
"query { ${setup(AllFilmsBlock())} }"
val starWars = query {
allFilms { // TODO }
}
class AllFilmsBlock {
fun allFilms(setup: FilmBlock.() !" String) =
"allFilms { ${setup(FilmBlock())} }"
}
fun query(setup: AllFilmsBlock.() !" String) =
"query { ${setup(AllFilmsBlock())} }"
val starWars = query {
allFilms { // TODO }
}
class AllFilmsBlock {
fun allFilms(setup: FilmBlock.() !" String) =
"allFilms { ${setup(FilmBlock())} }"
}
val starWars = query {
allFilms {
film {
// TODO
}
}
}
val starWars = query {
allFilms { film { } }
}
class FilmBlock {
fun film(setup: FilmFields.() !" String) =
with(FilmFields()) {
setup()
"film { ${fields()} }"
}
}
val starWars = query {
allFilms { film { } }
}
class FilmBlock {
fun film(setup: FilmFields.() !" String) =
with(FilmFields()) {
setup()
"film { ${fields()} }"
}
}
val starWars = query {
allFilms { film { } }
}
class FilmBlock {
fun film(setup: FilmFields.() !" String) =
with(FilmFields()) {
setup()
"film { ${fields()} }"
}
}
class FilmFiels {
private val picked = mutableListOf<String>()
fun fields() = TODO()
val title: String
get() {
picked.add(TITLE)
return TITLE
}
}
class FilmFields {
val title: String
get() { … }
val director: String
get() { … }
private companion object {
const val TITLE = "title"
const val DIRECTOR = "director"
}
}
class FilmFields {
fun fields() =
picked.distinct().joinToString(separator = " ")
val title: String
get() { … }
val director: String
get() { … }
private companion object { … }
}
class FilmFields {
fun fields() =
picked.distinct().joinToString(separator = " ")
val title: String
get() { … }
val director: String
get() { … }
private companion object { … }
}
val starWars = query {
allFilms {
film {
title
director
}
}
}
println(starWars)
// Plain old mockWebServer
val server = MockWebServer()
val response = MockResponse().apply {
setResponseCode(503)
setBody("Ops!")
}
server.enqueue(response)
server.start()
class MockResponseBuilder(
'( Aliases
var code: Int = 0,
var response: String? = null) {
fun mockResponse() = MockResponse().apply {
setResponseCode(code)
setBody(response)
}
}
class QueueBuilder {
val mocks = mutableListOf<MockResponse>()
fun enqueueMock(setup: MockResponseBuilder.() !" Unit) {
val builder = MockResponseBuilder()
builder.setup()
mocks.add(builder.mockResponse())
}
}
typealias BuildMock = MockResponseBuilder.() !" Unit
class QueueBuilder {
val mocks = mutableListOf<MockResponse>()
fun enqueueMock(setup: BuildMock) =
MockResponseBuilder().run {
setup()
mocks.add(mockResponse())
}
}
typealias BuildMock = MockResponseBuilder.() !" Unit
class QueueBuilder {
val mocks = mutableListOf<MockResponse>()
fun enqueueMock(setup: BuildMock) =
MockResponseBuilder().run {
setup()
mocks.add(mockResponse())
}
}
typealias BuildQueue = QueueBuilder.() !" Unit
fun newServer(setup: BuildQueue): MockWebServer =
with(MockWebServer()) {
'( ????
return this
}
typealias BuildQueue = QueueBuilder.() !" Unit
fun newServer(setup: BuildQueue): MockWebServer =
with(MockWebServer()) {
QueueBuilder().run {
setup()
mocks.forEach { enqueue(it) }
}
return this
}
typealias BuildQueue = QueueBuilder.() !" Unit
fun newServer(setup: BuildQueue): MockWebServer =
with(MockWebServer()) {
QueueBuilder().run {
setup()
mocks.forEach { enqueue(it) }
}
return this
}
// DSL based
val server = newServer {
enqueueMock {
code = 200
response = "OK"
}
}
server.start()
// Plain old mockWebServer
val server = MockWebServer()
val response = MockResponse().apply {
setResponseCode(503)
setBody("Ops!")
}
server.enqueue(response)
server.start()
FINAL

REMARKS
CONCLUSIONS
• DSLs are fun (with no pun)
• DSL-building offer great insights over Kotlin features!
• DSLs should work to improve an existing domain, not replace it
• Design your own DSLs for fun and profit !
https://speakerdeck.com/ubiratansoares
UBIRATAN
SOARES
Computer Scientist by ICMC/USP
Software Engineer, curious guy
Google Expert for Android and Kotlin
Teacher, speaker, etc, etc
THANK YOU
@ubiratanfsoares
ubiratansoares.github.io
https://br.linkedin.com/in/ubiratanfsoares

Contenu connexe

Tendances

Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
Dmitry Buzdin
 
関数潮流(Function Tendency)
関数潮流(Function Tendency)関数潮流(Function Tendency)
関数潮流(Function Tendency)
riue
 
Nik Graf - Get started with Reason and ReasonReact
Nik Graf - Get started with Reason and ReasonReactNik Graf - Get started with Reason and ReasonReact
Nik Graf - Get started with Reason and ReasonReact
OdessaJS Conf
 

Tendances (20)

Scalaz 8 vs Akka Actors
Scalaz 8 vs Akka ActorsScalaz 8 vs Akka Actors
Scalaz 8 vs Akka Actors
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 
関数潮流(Function Tendency)
関数潮流(Function Tendency)関数潮流(Function Tendency)
関数潮流(Function Tendency)
 
Nik Graf - Get started with Reason and ReasonReact
Nik Graf - Get started with Reason and ReasonReactNik Graf - Get started with Reason and ReasonReact
Nik Graf - Get started with Reason and ReasonReact
 
Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)
 
Google Guava
Google GuavaGoogle Guava
Google Guava
 
Basic java, java collection Framework and Date Time API
Basic java, java collection Framework and Date Time APIBasic java, java collection Framework and Date Time API
Basic java, java collection Framework and Date Time API
 
Google Guava - Core libraries for Java & Android
Google Guava - Core libraries for Java & AndroidGoogle Guava - Core libraries for Java & Android
Google Guava - Core libraries for Java & Android
 
Hive function-cheat-sheet
Hive function-cheat-sheetHive function-cheat-sheet
Hive function-cheat-sheet
 
WorkingWithSlick2.1.0
WorkingWithSlick2.1.0WorkingWithSlick2.1.0
WorkingWithSlick2.1.0
 
From java to kotlin beyond alt+shift+cmd+k
From java to kotlin beyond alt+shift+cmd+kFrom java to kotlin beyond alt+shift+cmd+k
From java to kotlin beyond alt+shift+cmd+k
 
Benefits of Kotlin
Benefits of KotlinBenefits of Kotlin
Benefits of Kotlin
 
Kotlin, why?
Kotlin, why?Kotlin, why?
Kotlin, why?
 
The Ring programming language version 1.5.1 book - Part 43 of 180
The Ring programming language version 1.5.1 book - Part 43 of 180The Ring programming language version 1.5.1 book - Part 43 of 180
The Ring programming language version 1.5.1 book - Part 43 of 180
 
Functional Scala 2020
Functional Scala 2020Functional Scala 2020
Functional Scala 2020
 
"Kotlin и rx в android" Дмитрий Воронин (Avito)
"Kotlin и rx в android" Дмитрий Воронин  (Avito)"Kotlin и rx в android" Дмитрий Воронин  (Avito)
"Kotlin и rx в android" Дмитрий Воронин (Avito)
 
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3
 
Functional Programming for OO Programmers (part 2)
Functional Programming for OO Programmers (part 2)Functional Programming for OO Programmers (part 2)
Functional Programming for OO Programmers (part 2)
 
Google Guava for cleaner code
Google Guava for cleaner codeGoogle Guava for cleaner code
Google Guava for cleaner code
 
JavaScript ∩ WebAssembly
JavaScript ∩ WebAssemblyJavaScript ∩ WebAssembly
JavaScript ∩ WebAssembly
 

Similaire à TDC218SP | Trilha Kotlin - DSLs in a Kotlin Way

pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 

Similaire à TDC218SP | Trilha Kotlin - DSLs in a Kotlin Way (20)

つくってあそぼ Kotlin DSL ~拡張編~
つくってあそぼ Kotlin DSL ~拡張編~つくってあそぼ Kotlin DSL ~拡張編~
つくってあそぼ Kotlin DSL ~拡張編~
 
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf MilanFrom Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
 
Kotlin for Android Developers - Victor Kropp - Codemotion Rome 2018
Kotlin for Android Developers - Victor Kropp - Codemotion Rome 2018Kotlin for Android Developers - Victor Kropp - Codemotion Rome 2018
Kotlin for Android Developers - Victor Kropp - Codemotion Rome 2018
 
SDC - Einführung in Scala
SDC - Einführung in ScalaSDC - Einführung in Scala
SDC - Einführung in Scala
 
2014-11-01 01 Денис Нелюбин. О сортах кофе
2014-11-01 01 Денис Нелюбин. О сортах кофе2014-11-01 01 Денис Нелюбин. О сортах кофе
2014-11-01 01 Денис Нелюбин. О сортах кофе
 
Swift 함수 커링 사용하기
Swift 함수 커링 사용하기Swift 함수 커링 사용하기
Swift 함수 커링 사용하기
 
EcmaScript unchained
EcmaScript unchainedEcmaScript unchained
EcmaScript unchained
 
Scala 2 + 2 > 4
Scala 2 + 2 > 4Scala 2 + 2 > 4
Scala 2 + 2 > 4
 
Kotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan SoaresKotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan Soares
 
Persisting Data on SQLite using Room
Persisting Data on SQLite using RoomPersisting Data on SQLite using Room
Persisting Data on SQLite using Room
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
6. Generics. Collections. Streams
6. Generics. Collections. Streams6. Generics. Collections. Streams
6. Generics. Collections. Streams
 
K is for Kotlin
K is for KotlinK is for Kotlin
K is for Kotlin
 
Hitchhiker's Guide to Functional Programming
Hitchhiker's Guide to Functional ProgrammingHitchhiker's Guide to Functional Programming
Hitchhiker's Guide to Functional Programming
 
Miracle of std lib
Miracle of std libMiracle of std lib
Miracle of std lib
 
OBJECTS IN Object Oriented Programming .ppt
OBJECTS IN Object Oriented Programming .pptOBJECTS IN Object Oriented Programming .ppt
OBJECTS IN Object Oriented Programming .ppt
 
Kotlin Generation
Kotlin GenerationKotlin Generation
Kotlin Generation
 

Plus de tdc-globalcode

Plus de tdc-globalcode (20)

TDC2019 Intel Software Day - Visao Computacional e IA a servico da humanidade
TDC2019 Intel Software Day - Visao Computacional e IA a servico da humanidadeTDC2019 Intel Software Day - Visao Computacional e IA a servico da humanidade
TDC2019 Intel Software Day - Visao Computacional e IA a servico da humanidade
 
TDC2019 Intel Software Day - Tecnicas de Programacao Paralela em Machine Lear...
TDC2019 Intel Software Day - Tecnicas de Programacao Paralela em Machine Lear...TDC2019 Intel Software Day - Tecnicas de Programacao Paralela em Machine Lear...
TDC2019 Intel Software Day - Tecnicas de Programacao Paralela em Machine Lear...
 
TDC2019 Intel Software Day - ACATE - Cases de Sucesso
TDC2019 Intel Software Day - ACATE - Cases de SucessoTDC2019 Intel Software Day - ACATE - Cases de Sucesso
TDC2019 Intel Software Day - ACATE - Cases de Sucesso
 
TDC2019 Intel Software Day - Otimizacao grafica com o Intel GPA
TDC2019 Intel Software Day - Otimizacao grafica com o Intel GPATDC2019 Intel Software Day - Otimizacao grafica com o Intel GPA
TDC2019 Intel Software Day - Otimizacao grafica com o Intel GPA
 
TDC2019 Intel Software Day - Deteccao de objetos em tempo real com OpenVino
TDC2019 Intel Software Day - Deteccao de objetos em tempo real com OpenVinoTDC2019 Intel Software Day - Deteccao de objetos em tempo real com OpenVino
TDC2019 Intel Software Day - Deteccao de objetos em tempo real com OpenVino
 
TDC2019 Intel Software Day - OpenCV: Inteligencia artificial e Visao Computac...
TDC2019 Intel Software Day - OpenCV: Inteligencia artificial e Visao Computac...TDC2019 Intel Software Day - OpenCV: Inteligencia artificial e Visao Computac...
TDC2019 Intel Software Day - OpenCV: Inteligencia artificial e Visao Computac...
 
TDC2019 Intel Software Day - Inferencia de IA em edge devices
TDC2019 Intel Software Day - Inferencia de IA em edge devicesTDC2019 Intel Software Day - Inferencia de IA em edge devices
TDC2019 Intel Software Day - Inferencia de IA em edge devices
 
Trilha BigData - Banco de Dados Orientado a Grafos na Seguranca Publica
Trilha BigData - Banco de Dados Orientado a Grafos na Seguranca PublicaTrilha BigData - Banco de Dados Orientado a Grafos na Seguranca Publica
Trilha BigData - Banco de Dados Orientado a Grafos na Seguranca Publica
 
Trilha .Net - Programacao funcional usando f#
Trilha .Net - Programacao funcional usando f#Trilha .Net - Programacao funcional usando f#
Trilha .Net - Programacao funcional usando f#
 
TDC2018SP | Trilha Go - Case Easylocus
TDC2018SP | Trilha Go - Case EasylocusTDC2018SP | Trilha Go - Case Easylocus
TDC2018SP | Trilha Go - Case Easylocus
 
TDC2018SP | Trilha Modern Web - Para onde caminha a Web?
TDC2018SP | Trilha Modern Web - Para onde caminha a Web?TDC2018SP | Trilha Modern Web - Para onde caminha a Web?
TDC2018SP | Trilha Modern Web - Para onde caminha a Web?
 
TDC2018SP | Trilha Go - Clean architecture em Golang
TDC2018SP | Trilha Go - Clean architecture em GolangTDC2018SP | Trilha Go - Clean architecture em Golang
TDC2018SP | Trilha Go - Clean architecture em Golang
 
TDC2018SP | Trilha Go - "Go" tambem e linguagem de QA
TDC2018SP | Trilha Go - "Go" tambem e linguagem de QATDC2018SP | Trilha Go - "Go" tambem e linguagem de QA
TDC2018SP | Trilha Go - "Go" tambem e linguagem de QA
 
TDC2018SP | Trilha Mobile - Digital Wallets - Seguranca, inovacao e tendencia
TDC2018SP | Trilha Mobile - Digital Wallets - Seguranca, inovacao e tendenciaTDC2018SP | Trilha Mobile - Digital Wallets - Seguranca, inovacao e tendencia
TDC2018SP | Trilha Mobile - Digital Wallets - Seguranca, inovacao e tendencia
 
TDC2018SP | Trilha .Net - Real Time apps com Azure SignalR Service
TDC2018SP | Trilha .Net - Real Time apps com Azure SignalR ServiceTDC2018SP | Trilha .Net - Real Time apps com Azure SignalR Service
TDC2018SP | Trilha .Net - Real Time apps com Azure SignalR Service
 
TDC2018SP | Trilha .Net - Passado, Presente e Futuro do .NET
TDC2018SP | Trilha .Net - Passado, Presente e Futuro do .NETTDC2018SP | Trilha .Net - Passado, Presente e Futuro do .NET
TDC2018SP | Trilha .Net - Passado, Presente e Futuro do .NET
 
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8TDC2018SP | Trilha .Net - Novidades do C# 7 e 8
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8
 
TDC2018SP | Trilha .Net - Obtendo metricas com TDD utilizando build automatiz...
TDC2018SP | Trilha .Net - Obtendo metricas com TDD utilizando build automatiz...TDC2018SP | Trilha .Net - Obtendo metricas com TDD utilizando build automatiz...
TDC2018SP | Trilha .Net - Obtendo metricas com TDD utilizando build automatiz...
 
TDC2018SP | Trilha .Net - .NET funcional com F#
TDC2018SP | Trilha .Net - .NET funcional com F#TDC2018SP | Trilha .Net - .NET funcional com F#
TDC2018SP | Trilha .Net - .NET funcional com F#
 
TDC2018SP | Trilha .Net - Crie SPAs com Razor e C# usando Blazor em .Net Core
TDC2018SP | Trilha .Net - Crie SPAs com Razor e C# usando Blazor  em .Net CoreTDC2018SP | Trilha .Net - Crie SPAs com Razor e C# usando Blazor  em .Net Core
TDC2018SP | Trilha .Net - Crie SPAs com Razor e C# usando Blazor em .Net Core
 

Dernier

Jual Obat Aborsi Hongkong ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...
Jual Obat Aborsi Hongkong ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...Jual Obat Aborsi Hongkong ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...
Jual Obat Aborsi Hongkong ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...
ZurliaSoop
 

Dernier (20)

Accessible Digital Futures project (20/03/2024)
Accessible Digital Futures project (20/03/2024)Accessible Digital Futures project (20/03/2024)
Accessible Digital Futures project (20/03/2024)
 
HMCS Max Bernays Pre-Deployment Brief (May 2024).pptx
HMCS Max Bernays Pre-Deployment Brief (May 2024).pptxHMCS Max Bernays Pre-Deployment Brief (May 2024).pptx
HMCS Max Bernays Pre-Deployment Brief (May 2024).pptx
 
Understanding Accommodations and Modifications
Understanding  Accommodations and ModificationsUnderstanding  Accommodations and Modifications
Understanding Accommodations and Modifications
 
FSB Advising Checklist - Orientation 2024
FSB Advising Checklist - Orientation 2024FSB Advising Checklist - Orientation 2024
FSB Advising Checklist - Orientation 2024
 
This PowerPoint helps students to consider the concept of infinity.
This PowerPoint helps students to consider the concept of infinity.This PowerPoint helps students to consider the concept of infinity.
This PowerPoint helps students to consider the concept of infinity.
 
Fostering Friendships - Enhancing Social Bonds in the Classroom
Fostering Friendships - Enhancing Social Bonds  in the ClassroomFostering Friendships - Enhancing Social Bonds  in the Classroom
Fostering Friendships - Enhancing Social Bonds in the Classroom
 
REMIFENTANIL: An Ultra short acting opioid.pptx
REMIFENTANIL: An Ultra short acting opioid.pptxREMIFENTANIL: An Ultra short acting opioid.pptx
REMIFENTANIL: An Ultra short acting opioid.pptx
 
ICT role in 21st century education and it's challenges.
ICT role in 21st century education and it's challenges.ICT role in 21st century education and it's challenges.
ICT role in 21st century education and it's challenges.
 
Making communications land - Are they received and understood as intended? we...
Making communications land - Are they received and understood as intended? we...Making communications land - Are they received and understood as intended? we...
Making communications land - Are they received and understood as intended? we...
 
Towards a code of practice for AI in AT.pptx
Towards a code of practice for AI in AT.pptxTowards a code of practice for AI in AT.pptx
Towards a code of practice for AI in AT.pptx
 
Sensory_Experience_and_Emotional_Resonance_in_Gabriel_Okaras_The_Piano_and_Th...
Sensory_Experience_and_Emotional_Resonance_in_Gabriel_Okaras_The_Piano_and_Th...Sensory_Experience_and_Emotional_Resonance_in_Gabriel_Okaras_The_Piano_and_Th...
Sensory_Experience_and_Emotional_Resonance_in_Gabriel_Okaras_The_Piano_and_Th...
 
Interdisciplinary_Insights_Data_Collection_Methods.pptx
Interdisciplinary_Insights_Data_Collection_Methods.pptxInterdisciplinary_Insights_Data_Collection_Methods.pptx
Interdisciplinary_Insights_Data_Collection_Methods.pptx
 
Sociology 101 Demonstration of Learning Exhibit
Sociology 101 Demonstration of Learning ExhibitSociology 101 Demonstration of Learning Exhibit
Sociology 101 Demonstration of Learning Exhibit
 
ICT Role in 21st Century Education & its Challenges.pptx
ICT Role in 21st Century Education & its Challenges.pptxICT Role in 21st Century Education & its Challenges.pptx
ICT Role in 21st Century Education & its Challenges.pptx
 
How to setup Pycharm environment for Odoo 17.pptx
How to setup Pycharm environment for Odoo 17.pptxHow to setup Pycharm environment for Odoo 17.pptx
How to setup Pycharm environment for Odoo 17.pptx
 
Single or Multiple melodic lines structure
Single or Multiple melodic lines structureSingle or Multiple melodic lines structure
Single or Multiple melodic lines structure
 
Unit-V; Pricing (Pharma Marketing Management).pptx
Unit-V; Pricing (Pharma Marketing Management).pptxUnit-V; Pricing (Pharma Marketing Management).pptx
Unit-V; Pricing (Pharma Marketing Management).pptx
 
Micro-Scholarship, What it is, How can it help me.pdf
Micro-Scholarship, What it is, How can it help me.pdfMicro-Scholarship, What it is, How can it help me.pdf
Micro-Scholarship, What it is, How can it help me.pdf
 
Jual Obat Aborsi Hongkong ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...
Jual Obat Aborsi Hongkong ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...Jual Obat Aborsi Hongkong ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...
Jual Obat Aborsi Hongkong ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...
 
Jamworks pilot and AI at Jisc (20/03/2024)
Jamworks pilot and AI at Jisc (20/03/2024)Jamworks pilot and AI at Jisc (20/03/2024)
Jamworks pilot and AI at Jisc (20/03/2024)
 

TDC218SP | Trilha Kotlin - DSLs in a Kotlin Way

  • 1. DSLs IN A KOTLIN WAY Ubiratan Soares July / 2018 VERSION 2.0
  • 2.
  • 5. String sql = SQLiteQueryBuilder .select("*") .from("accounts") .where("id=12345") .toString(); https://github.com/alexfu/SQLiteQueryBuilder
  • 7. val tree = createHTMLDocument().html { body { h1 { +"Hey" } div { +"Ho!" span { +"Lets go!" } } } } https://github.com/Kotlin/kotlinx.html
  • 8.
  • 9.
  • 10.
  • 12. Type Aliases Sealed Classes Extension Functions Extension Properties ETC
  • 15. class Extractor { fun firstLetter(target: String) = target[0].toString() } val k = Extractor().firstLetter("Kotlin")
  • 16. class Extractor { infix fun firstLetter(target: String) = target[0].toString() } val k = Extractor() firstLetter "Kotlin" 👌
  • 17. object extract { infix fun firstLetterOf(target: String) = target[0].toString() }
  • 18. object extract { infix fun firstLetterOf(target: String) = target[0].toString() } val first = extract firstLetterOf "Awesome"
  • 19.
  • 20. object acronymn { infix fun from(target: String) = Chainer( initials = mutableListOf(), seed = target ) }
  • 21. object acronymn { infix fun from(target: String) = Chainer( initials = mutableListOf(), seed = target ) }
  • 22. class Chainer( private val initials: MutableList<String>, seed: String) { init { initials += seed.first().toString() }
  • 23. class Chainer(…) { init { initials += seed.first().toString() } infix fun and(another: String) = Chainer(initials, another)
  • 24. class Chainer(…) { init { initials += seed.first().toString() } infix fun and(another: String) = Chainer(initials, another)
  • 25. sealed class Joiner object noPunctuaction : Joiner() object dots : Joiner()
  • 26. class Chainer(…) { infix fun joinedWith(option: Joiner) = initials.reduce { previous, letter !" val next = when (option) { is noPunctuaction !" letter is dots !" "$letter." } "$previous$next" }
  • 27. class Chainer(…) { infix fun joinedWith(option: Joiner) = initials.reduce { previous, letter !" val next = when (option) { is noPunctuaction !" letter is dots !" "$letter." } "$previous$next" }
  • 28. class Chainer(…) { infix fun joinedWith(option: Joiner) = initials.reduce { previous, letter !" val next = when (option) { is noPunctuaction !" letter is dots !" "$letter." } "$previous$next" }
  • 29. class Chainer(…) { infix fun joinedWith(option: Joiner) = initials.reduce { previous, letter !" val next = when (option) { is noPunctuaction !" letter is dots !" "$letter." } "$previous$next" }
  • 30. val dsl = acronymn from "Domain" and "Specific" and "Language" joinedWith noPunctuaction //DSL
  • 31. val dsl = acronymn from "Domain" and "Specific" and "Language" joinedWith dots //D.S.L
  • 33. val items = mutableListOf(1, 2, 3) items += 4
  • 34. val items = mutableListOf(1, 2, 3) items += 4 /#$ * Adds the specified [element] to this mutable collection. %& @kotlin.internal.InlineOnly public inline operator fun <T> MutableCollection<in T>.plusAssign(element: T) { this.add(element) }
  • 35. typealias IntPair = Pair<Int, Int> val calendar by lazy { Calendar.getInstance() }
  • 36. operator fun Date.plus(args: IntPair): Date { calendar.time = this calendar.add(args.first, args.second) return calendar.time } operator fun Date.minus(args: IntPair): Date { calendar.time = this calendar.add(args.first, -args.second) return calendar.time }
  • 37. operator fun Date.plus(args: IntPair): Date { calendar.time = this calendar.add(args.first, args.second) return calendar.time } operator fun Date.minus(args: IntPair): Date { calendar.time = this calendar.add(args.first, -args.second) return calendar.time }
  • 38. fun Int.days() = Calendar.DAY_OF_YEAR to this fun Int.months() = Calendar.MONTH to this val atPast = Date() - 2.months() val atFuture = Date() + 15.days()
  • 39. val past = Date() - 2.months val future = Date() + 15.days 👌 val Int.days: IntPair get() = Calendar.DAY_OF_YEAR to this val Int.months: IntPair get() = Calendar.MONTH to this
  • 40. A The problem like with spannables on Android
  • 41. val toSpan = SpannableStringBuilder() val start = toSpan.length toSpan.append("First Part") toSpan.setSpan( UnderlineSpan(), start, toSpan.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE ) toSpan.setSpan( StyleSpan(android.graphics.Typeface.BOLD), start, toSpan.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE ) toSpan.append("not bold or underlined")
  • 42. operator fun SpannableString.plus(s: String) = SpannableString(TextUtils.concat(this, s)) operator fun SpannableString.plus(s: SpannableString) = SpannableString(TextUtils.concat(this, s))
  • 43. fun span(given: CharSequence, span: Any): SpannableString { val spannable = if (given is String) SpannableString(given) else given as? SpannableString ?: throw CannotBeSpanned return spannable.apply { setSpan(span, 0, length, SPAN_EXCLUSIVE_EXCLUSIVE) } } object CannotBeSpanned : IllegalArgumentException( "Cannot apply span. Should be String or SpannableString" )
  • 44. // Add more hooks to same span() function fun italic(given: CharSequence) = span(given, StyleSpan(Typeface.ITALIC)) fun underline(given: CharSequence) = span(given, UnderlineSpan()) fun bold(given: CharSequence) = span(given, StyleSpan(Typeface.BOLD))
  • 45. val spanned = "normal" + bold("bold") + italic("italic") label.setText(spanned)
  • 47. fun x(lambda: () !" Unit) { lambda() } fun y(lambda: () !" Int) = lambda() val x: () !" Int = { TODO() } val result = x()
  • 48. val add = fun(a: Int, b: Int) = a + b fun calculate(func: (Int, Int) !" Int) { func.invoke(2,2) } // Trailling Notation calculate { a, b !" a + b } // Normal notation calculate(add)
  • 49. class Receiver(val data: Int) // Kotlin allows us to add an extension function // literal to a type. Such lambda acquires the // properties of non-static method in the context val addOne: Receiver.() !" Int = { data + 1 } val two = addOne(Receiver(1)) val twoAgain = Receiver(1).addOne()
  • 50. fun receive(block: Receiver.() !" Unit) { val r = Receiver(data = 1) block(r) // r.block() is exactly the same } receive { println(data) // 1 }
  • 51.
  • 53. val starWars = query { allFilms { film { title director } } } println(starWars) > query { allFilms { film { title director } } }
  • 54. val starWars = query { '( TODO }
  • 55. val starWars = query { '( TODO } fun query(): String { return "query { ${ '( Something here } }" }
  • 56. val starWars = query { '( TODO } fun query(setup: AllFilmsBlock.() !" String) = "query { ${setup(AllFilmsBlock())} }"
  • 57. val starWars = query { '( TODO } fun query(setup: AllFilmsBlock.() !" String) = "query { ${setup(AllFilmsBlock())} }"
  • 58. val starWars = query { '( TODO } fun query(setup: AllFilmsBlock.() !" String) = "query { ${setup(AllFilmsBlock())} }"
  • 59. fun query(setup: AllFilmsBlock.() !" String) = "query { ${setup(AllFilmsBlock())} }" val starWars = query { allFilms { // TODO } } class AllFilmsBlock { fun allFilms(setup: FilmBlock.() !" String) = "allFilms { ${setup(FilmBlock())} }" }
  • 60. fun query(setup: AllFilmsBlock.() !" String) = "query { ${setup(AllFilmsBlock())} }" val starWars = query { allFilms { // TODO } } class AllFilmsBlock { fun allFilms(setup: FilmBlock.() !" String) = "allFilms { ${setup(FilmBlock())} }" }
  • 61. val starWars = query { allFilms { film { // TODO } } }
  • 62. val starWars = query { allFilms { film { } } } class FilmBlock { fun film(setup: FilmFields.() !" String) = with(FilmFields()) { setup() "film { ${fields()} }" } }
  • 63. val starWars = query { allFilms { film { } } } class FilmBlock { fun film(setup: FilmFields.() !" String) = with(FilmFields()) { setup() "film { ${fields()} }" } }
  • 64. val starWars = query { allFilms { film { } } } class FilmBlock { fun film(setup: FilmFields.() !" String) = with(FilmFields()) { setup() "film { ${fields()} }" } }
  • 65. class FilmFiels { private val picked = mutableListOf<String>() fun fields() = TODO() val title: String get() { picked.add(TITLE) return TITLE } }
  • 66. class FilmFields { val title: String get() { … } val director: String get() { … } private companion object { const val TITLE = "title" const val DIRECTOR = "director" } }
  • 67. class FilmFields { fun fields() = picked.distinct().joinToString(separator = " ") val title: String get() { … } val director: String get() { … } private companion object { … } }
  • 68. class FilmFields { fun fields() = picked.distinct().joinToString(separator = " ") val title: String get() { … } val director: String get() { … } private companion object { … } }
  • 69. val starWars = query { allFilms { film { title director } } } println(starWars)
  • 70.
  • 71. // Plain old mockWebServer val server = MockWebServer() val response = MockResponse().apply { setResponseCode(503) setBody("Ops!") } server.enqueue(response) server.start()
  • 72. class MockResponseBuilder( '( Aliases var code: Int = 0, var response: String? = null) { fun mockResponse() = MockResponse().apply { setResponseCode(code) setBody(response) } }
  • 73. class QueueBuilder { val mocks = mutableListOf<MockResponse>() fun enqueueMock(setup: MockResponseBuilder.() !" Unit) { val builder = MockResponseBuilder() builder.setup() mocks.add(builder.mockResponse()) } }
  • 74. typealias BuildMock = MockResponseBuilder.() !" Unit class QueueBuilder { val mocks = mutableListOf<MockResponse>() fun enqueueMock(setup: BuildMock) = MockResponseBuilder().run { setup() mocks.add(mockResponse()) } }
  • 75. typealias BuildMock = MockResponseBuilder.() !" Unit class QueueBuilder { val mocks = mutableListOf<MockResponse>() fun enqueueMock(setup: BuildMock) = MockResponseBuilder().run { setup() mocks.add(mockResponse()) } }
  • 76. typealias BuildQueue = QueueBuilder.() !" Unit fun newServer(setup: BuildQueue): MockWebServer = with(MockWebServer()) { '( ???? return this }
  • 77. typealias BuildQueue = QueueBuilder.() !" Unit fun newServer(setup: BuildQueue): MockWebServer = with(MockWebServer()) { QueueBuilder().run { setup() mocks.forEach { enqueue(it) } } return this }
  • 78. typealias BuildQueue = QueueBuilder.() !" Unit fun newServer(setup: BuildQueue): MockWebServer = with(MockWebServer()) { QueueBuilder().run { setup() mocks.forEach { enqueue(it) } } return this }
  • 79. // DSL based val server = newServer { enqueueMock { code = 200 response = "OK" } } server.start() // Plain old mockWebServer val server = MockWebServer() val response = MockResponse().apply { setResponseCode(503) setBody("Ops!") } server.enqueue(response) server.start()
  • 80.
  • 82. CONCLUSIONS • DSLs are fun (with no pun) • DSL-building offer great insights over Kotlin features! • DSLs should work to improve an existing domain, not replace it • Design your own DSLs for fun and profit !
  • 84. UBIRATAN SOARES Computer Scientist by ICMC/USP Software Engineer, curious guy Google Expert for Android and Kotlin Teacher, speaker, etc, etc