Slide 1

Slide 1 text

Kotlin’s Mind Blowers Eugenio Marletti @workingkills

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

@Deprecated("Just don't.") fun deprecatedFun(age: Int, name: String) { !" nasty stuff } data class Name(val name: String) data class Age(val age: Int) fun niceFun(name: Name, age: Age) { !" good stuff } fun usage(myName: String, myAge: Int) { !" ⚠ 'deprecatedFun(Int, String): Unit' is deprecated. Just Don't. deprecatedFun(myAge, myName) }

Slide 5

Slide 5 text

@Deprecated("Just don't.", level = DeprecationLevel.WARNING) fun deprecatedFun(age: Int, name: String) { !" nasty stuff } data class Name(val name: String) data class Age(val age: Int) fun niceFun(name: Name, age: Age) { !" good stuff } fun usage(myName: String, myAge: Int) { !" ⚠ 'deprecatedFun(Int, String): Unit' is deprecated. Just Don't. deprecatedFun(myAge, myName) }

Slide 6

Slide 6 text

@Deprecated("Just don't.", level = DeprecationLevel.ERROR) fun deprecatedFun(age: Int, name: String) { !" nasty stuff } data class Name(val name: String) data class Age(val age: Int) fun niceFun(name: Name, age: Age) { !" good stuff } fun usage(myName: String, myAge: Int) { !" ❌ Using 'deprecatedFun(Int, String): Unit' is an error. Just Don't. deprecatedFun(myAge, myName) }

Slide 7

Slide 7 text

@Deprecated("Just don't.", level = DeprecationLevel.HIDDEN) fun deprecatedFun(age: Int, name: String) { !" nasty stuff } data class Name(val name: String) data class Age(val age: Int) fun niceFun(name: Name, age: Age) { !" good stuff } fun usage(myName: String, myAge: Int) { !" ❌ Unresolved reference: deprecatedFun deprecatedFun(myAge, myName) }

Slide 8

Slide 8 text

@Deprecated("Just don't.", ReplaceWith("niceFun(Name(name), Age(age))")) fun deprecatedFun(age: Int, name: String) { !" nasty stuff } data class Name(val name: String) data class Age(val age: Int) fun niceFun(name: Name, age: Age) { !" good stuff } fun usage(myName: String, myAge: Int) { !" # deprecatedFun(myAge, myName) }

Slide 9

Slide 9 text

@Deprecated("Just don't.", ReplaceWith("niceFun(Name(name), Age(age))")) fun deprecatedFun(age: Int, name: String) { !" nasty stuff } data class Name(val name: String) data class Age(val age: Int) fun niceFun(name: Name, age: Age) { !" good stuff } fun usage(myName: String, myAge: Int) { !" # deprecatedFun(myAge, myName) }

Slide 10

Slide 10 text

@Deprecated("Just don't.", ReplaceWith("niceFun(Name(name), Age(age))")) fun deprecatedFun(age: Int, name: String) { !" nasty stuff } data class Name(val name: String) data class Age(val age: Int) fun niceFun(name: Name, age: Age) { !" good stuff } fun usage(myName: String, myAge: Int) { !" # deprecatedFun(myAge, myName) }

Slide 11

Slide 11 text

@Deprecated("Just don't.", ReplaceWith("niceFun(Name(name), Age(age))")) fun deprecatedFun(age: Int, name: String) { !" nasty stuff } data class Name(val name: String) data class Age(val age: Int) fun niceFun(name: Name, age: Age) { !" good stuff } fun usage(myName: String, myAge: Int) { !" ✅ niceFun(Name(myName), Age(myAge)) }

Slide 12

Slide 12 text

typealias TotallyNotThatClass = ThatClass

Slide 13

Slide 13 text

typealias AbsSubject = Subject

Slide 14

Slide 14 text

class BoringClass { fun washDishes() = "maybe later" } fun usage() { BoringClass().washDishes() }

Slide 15

Slide 15 text

class ExcitingClass { fun washDishes() = "maybe later" } fun usage() { BoringClass().washDishes() }

Slide 16

Slide 16 text

class ExcitingClass { fun washDishes() = "maybe later" } fun usage() { !" ❌ Unresolved reference: BoringClass BoringClass().washDishes() }

Slide 17

Slide 17 text

@Deprecated("Stop being boring.") typealias BoringClass = ExcitingClass class ExcitingClass { fun washDishes() = "maybe later" } fun usage() { !" ⚠ 'typealias BoringClass = ExcitingClass' is deprecated. !" Stop being boring. BoringClass().washDishes() }

Slide 18

Slide 18 text

@Deprecated("Stop being boring.", ReplaceWith("ExcitingClass")) typealias BoringClass = ExcitingClass class ExcitingClass { fun washDishes() = "maybe later" } fun usage() { !" ⚠ 'typealias BoringClass = ExcitingClass' is deprecated. !" Stop being boring. BoringClass().washDishes() }

Slide 19

Slide 19 text

package first fun topLevelFunction(i: Int) = i fun topLevelFunction(s: String) = s

Slide 20

Slide 20 text

package first fun topLevelFunction(i: Int) = i fun topLevelFunction(s: String) = s ----------------------------------- package second import first.topLevelFunction

Slide 21

Slide 21 text

package my.package data class ColorInt(val color: Int)

Slide 22

Slide 22 text

package my.package import android.support.annotation.ColorInt data class ColorInt(@ColorInt val color: Int)

Slide 23

Slide 23 text

package my.package import android.support.annotation.ColorInt data class ColorInt(@ColorInt val color: Int) --------------------------------------------- package not.my.package !" ❌ Conflicting import, imported name 'ColorInt' is ambiguous import android.support.annotation.ColorInt import my.package.ColorInt

Slide 24

Slide 24 text

package my.package import android.support.annotation.ColorInt data class ColorInt(@ColorInt val color: Int) --------------------------------------------- package not.my.package !" ✅ import android.support.annotation.ColorInt as ColorIntAnnotation import my.package.ColorInt

Slide 25

Slide 25 text

package my.package import android.support.annotation.ColorInt data class ColorInt(@ColorInt val color: Int) --------------------------------------------- package not.my.package !" ✅ import android.support.annotation.ColorInt as ColorIntAnnotationDuplicate import android.support.annotation.ColorInt as ColorIntAnnotation import my.package.ColorInt

Slide 26

Slide 26 text

fun oppaFunctionalStyle(list: List) = list.map { it.toCharArray().map { if (it.isDigit()) return@map CharArray(0) !" which map? % else it.toUpperCase() } }

Slide 27

Slide 27 text

fun oppaFunctionalStyle(list: List) = list.map listMap@ { it.toCharArray().map charMap@ { if (it.isDigit()) return@listMap CharArray(0) !" that map! & else it.toUpperCase() } }

Slide 28

Slide 28 text

fun stringLengthOrNull(maybeString: Any?) = if (maybeString is String) maybeString.length else null

Slide 29

Slide 29 text

fun stringLengthOrNull(maybeString: Any?) = (maybeString as? String)!#length

Slide 30

Slide 30 text

fun printEverything(vararg args: String) { println(args) } fun usage(stringArray: Array) { printEverything(*stringArray) }

Slide 31

Slide 31 text

fun printEverything(vararg args: String) { println(args) } fun usage( singleString: String, anotherSingleString: String, stringArray: Array, anotherStringArray: Array) { printEverything(*stringArray) }

Slide 32

Slide 32 text

fun printEverything(vararg args: String) { println(args) } fun usage( singleString: String, anotherSingleString: String, stringArray: Array, anotherStringArray: Array) { printEverything( singleString, *stringArray, anotherSingleString, *anotherStringArray) }

Slide 33

Slide 33 text

fun veryDescriptiveFun( arg1: String, arg2: Int, arg3: Int, arg4: Boolean ) = "meh"

Slide 34

Slide 34 text

fun veryDescriptiveFun( arg1: String, arg2: Int = arg1.length, arg3: Int = arg2, arg4: Boolean ) = "cool"

Slide 35

Slide 35 text

fun veryDescriptiveFun( arg1: String, arg2: Int = arg1.length, arg3: Int = arg2, arg4: Boolean = loadEntireDbInMemory()!#isEmpty() !& areYouSure() ) = "oh no"

Slide 36

Slide 36 text

fun iterate(iterable: Iterable) { iterable .onEach { println(it) } .map { it.length } .forEach { println(it) } } fun sequentiate(sequence: Sequence) { sequence .onEach { println(it) } .map { it.length } .forEach { println(it) } } fun usage() { val strings = listOf("a", "bb", "ccc") iterate(strings.asIterable()) sequentiate(strings.asSequence()) }

Slide 37

Slide 37 text

fun iterate(iterable: Iterable) { !" iterable !" .onEach { println(it) } !" .map { it.length } !" .forEach { println(it) } !" } !" fun sequentiate(sequence: Sequence) { !" sequence !" .onEach { println(it) } !" .map { it.length } !" .forEach { println(it) } !" } !" fun usage() { val strings = listOf("a", "bb", "ccc") iterate(strings.asIterable()) sequentiate(strings.asSequence()) }

Slide 38

Slide 38 text

fun iterate(iterable: Iterable) { !" a iterable !" bb .onEach { println(it) } !" ccc .map { it.length } !" 1 .forEach { println(it) } !" 2 } !" 3 fun sequentiate(sequence: Sequence) { !" sequence !" .onEach { println(it) } !" .map { it.length } !" .forEach { println(it) } !" } !" fun usage() { val strings = listOf("a", "bb", "ccc") iterate(strings.asIterable()) sequentiate(strings.asSequence()) }

Slide 39

Slide 39 text

fun iterate(iterable: Iterable) { !" a iterable !" bb .onEach { println(it) } !" ccc .map { it.length } !" 1 .forEach { println(it) } !" 2 } !" 3 fun sequentiate(sequence: Sequence) { !" a sequence !" 1 .onEach { println(it) } !" bb .map { it.length } !" 2 .forEach { println(it) } !" ccc } !" 3 fun usage() { val strings = listOf("a", "bb", "ccc") iterate(strings.asIterable()) sequentiate(strings.asSequence()) }

Slide 40

Slide 40 text

void

Slide 41

Slide 41 text

void !" not a type

Slide 42

Slide 42 text

void !' Unit

Slide 43

Slide 43 text

void !' Unit “In type theory, a unit type is a type that allows only one value.”

Slide 44

Slide 44 text

void !' Unit !" single instance

Slide 45

Slide 45 text

fun unity() { }

Slide 46

Slide 46 text

fun unity(): Unit { }

Slide 47

Slide 47 text

fun unity() = Unit

Slide 48

Slide 48 text

fun unity() = println("sweet")

Slide 49

Slide 49 text

fun unity() = java.lang.System.out.println("sweet")

Slide 50

Slide 50 text

Void

Slide 51

Slide 51 text

Void !" a type that can’t be instantiated

Slide 52

Slide 52 text

Void !' Nothing

Slide 53

Slide 53 text

Void !' Nothing “In type theory, the bottom type is the type that has no values.” bottom zero empty

Slide 54

Slide 54 text

Void !' Nothing !" a type that can’t be instantiated (same!)

Slide 55

Slide 55 text

Void !' Nothing?

Slide 56

Slide 56 text

fun foreverNull(): Nothing? = null

Slide 57

Slide 57 text

fun inifinite() { while (true) { !" nap } } fun naive() { inifinite() !" always believe in yourself!⚠ println("I've achieved all my hopes and dreams!") }

Slide 58

Slide 58 text

fun inifinite(): Nothing { while (true) { !" nap } } fun naive() { inifinite() !" ⚠ Unreachable code println("I've achieved all my hopes and dreams!") }

Slide 59

Slide 59 text

fun fiveMoreMinutesPlease(): VeryComplexType

Slide 60

Slide 60 text

fun fiveMoreMinutesPlease(): VeryComplexType = TODO()

Slide 61

Slide 61 text

fun fiveMoreMinutesPlease(): VeryComplexType = TODO() fun TODO(): Nothing = throw NotImplementedError()

Slide 62

Slide 62 text

data class Person( val name: String, val age: Int, val likesDataClasses: Boolean)

Slide 63

Slide 63 text

data class Person( val name: String, val age: Int, val likesDataClasses: Boolean) fun parsePerson(map: Map): Person? { val name = map["name"] if (name is String) { val age = map["age"] if (age is Int) { val likesDataClasses = map["likes-data-classes"] if (likesDataClasses is Boolean) { return Person( name, age, likesDataClasses) } } } return null }

Slide 64

Slide 64 text

data class Person( val name: String, val age: Int, val likesDataClasses: Boolean) fun parsePerson(map: Map): Person? { val name = map["name"] if (name !is String) return null val age = map["age"] if (age !is Int) return null val likesDataClasses = map["likes-data-classes"] if (likesDataClasses !is Boolean) return null return Person( name, age, likesDataClasses) }

Slide 65

Slide 65 text

data class Person( val name: String, val age: Int, val likesDataClasses: Boolean) fun parsePerson(map: Map): Person? { val name = map["name"] as? String !& return null val age = map["age"] as? Int !& return null val likesDataClasses = map["likes-data-classes"] as? Boolean !& return null return Person( name, age, likesDataClasses) }

Slide 66

Slide 66 text

data class Person( val name: String, val age: Int, val likesDataClasses: Boolean) fun parsePerson(map: Map): Person? { return Person( map["name"] as? String !& return null, map["age"] as? Int !& return null, map["likes-data-classes"] as? Boolean !& return null) }

Slide 67

Slide 67 text

!" Elvis operator !&

Slide 68

Slide 68 text

!& "hey"

Slide 69

Slide 69 text

a += b a.plusAssign(b) a -= b a.minusAssign(b) a!* a.inc() a!, a.dec() a + b a.plus(b) a - b a.minus(b) a * b a.times(b) a / b a.div(b) a % b a.rem(b) a!-b a.rangeTo(b) +a a.unaryPlus() -a a.unaryMinus() !a a.not()

Slide 70

Slide 70 text

a[i] a.get(i) a[i_1, !!., i_n] a.get(i_1, !!., i_n) a += b a.plusAssign(b) a -= b a.minusAssign(b) a *= b a.timesAssign(b) a !/ b a.divAssign(b) a %= b a.remAssign(b) a!* a.inc() a!, a.dec() a + b a.plus(b) a - b a.minus(b) a * b a.times(b) a / b a.div(b) a % b a.rem(b) a!-b a.rangeTo(b) +a a.unaryPlus() -a a.unaryMinus() !a a.not()

Slide 71

Slide 71 text

a > b a.compareTo(b) > 0 a < b a.compareTo(b) < 0 a !0 b a.compareTo(b) !0 0 a !1 b a.compareTo(b) !1 0 a[i] a.get(i) a[i_1, !!., i_n] a.get(i_1, !!., i_n) a[i] = b a.set(i, b) a[i_1, !!., i_n] = b a.set(i_1, !!., i_n, b) a += b a.plusAssign(b) a -= b a.minusAssign(b) a *= b a.timesAssign(b) a !/ b a.divAssign(b) a %= b a.remAssign(b) a!* a.inc() a!, a.dec() a + b a.plus(b) a - b a.minus(b) a * b a.times(b) a / b a.div(b) a % b a.rem(b) a!-b a.rangeTo(b) !a a.not()

Slide 72

Slide 72 text

a() a.invoke() a(i) a.invoke(i) a in b b.contains(a) a !in b !b.contains(a) a > b a.compareTo(b) > 0 a < b a.compareTo(b) < 0 a !0 b a.compareTo(b) !0 0 a !1 b a.compareTo(b) !1 0 a[i] a.get(i) a[i_1, !!., i_n] a.get(i_1, !!., i_n) a[i] = b a.set(i, b) a[i_1, !!., i_n] = b a.set(i_1, !!., i_n, b) a += b a.plusAssign(b) a -= b a.minusAssign(b) a *= b a.timesAssign(b) a !/ b a.divAssign(b) a %= b a.remAssign(b) a - b a.minus(b) a * b a.times(b) a / b a.div(b) a % b a.rem(b) a!-b a.rangeTo(b)

Slide 73

Slide 73 text

a() a.invoke() a(i) a.invoke(i) a(i_1, !!., i_n) a.invoke(i_1, !!., i_n) a in b b.contains(a) a !in b !b.contains(a) a > b a.compareTo(b) > 0 a < b a.compareTo(b) < 0 a !0 b a.compareTo(b) !0 0 a !1 b a.compareTo(b) !1 0 a[i] a.get(i) a[i_1, !!., i_n] a.get(i_1, !!., i_n) a[i] = b a.set(i, b) a[i_1, !!., i_n] = b a.set(i_1, !!., i_n, b) a += b a.plusAssign(b) a -= b a.minusAssign(b) a *= b a.timesAssign(b) a !/ b a.divAssign(b) a %= b a.remAssign(b)

Slide 74

Slide 74 text

a() a.invoke() a(i) a.invoke(i) a(i_1, !!., i_n) a.invoke(i_1, !!., i_n) a in b b.contains(a) a !in b !b.contains(a) a > b a.compareTo(b) > 0 a < b a.compareTo(b) < 0 a !0 b a.compareTo(b) !0 0 a !1 b a.compareTo(b) !1 0 a[i] a.get(i) a[i_1, !!., i_n] a.get(i_1, !!., i_n) a[i] = b a.set(i, b) a[i_1, !!., i_n] = b a.set(i_1, !!., i_n, b) a %= b a.remAssign(b)

Slide 75

Slide 75 text

a() a.invoke() a(i) a.invoke(i) a(i_1, !!., i_n) a.invoke(i_1, !!., i_n) a in b b.contains(a) a !in b !b.contains(a) a > b a.compareTo(b) > 0 a < b a.compareTo(b) < 0 a !0 b a.compareTo(b) !0 0 a !1 b a.compareTo(b) !1 0 a[i_1, !!., i_n] a.get(i_1, !!., i_n) a[i] = b a.set(i, b) a[i_1, !!., i_n] = b a.set(i_1, !!., i_n, b)

Slide 76

Slide 76 text

getValue, setValue, provideDelegate val someValue by lazy { "don't judge me" }

Slide 77

Slide 77 text

No content

Slide 78

Slide 78 text

No content

Slide 79

Slide 79 text

Kotlin tools team lead @ JetBrains co-author of “Kotlin in Action” @intelliyole on Twitter “Dmitry Jemerov” in “real life” yole

Slide 80

Slide 80 text

“ ” “ ” Kotlin tools team lead @ JetBrains co-author of “Kotlin in Action” @intelliyole on Twitter “Dmitry Jemerov” in “real life” yole

Slide 81

Slide 81 text

bit.ly/kotlin-mind-blowers Eugenio Marletti @workingkills