Slide 1

Slide 1 text

Sergey Ryabov

Slide 2

Slide 2 text

Inline Functions fun nthFibonacciNumber(n: Int): Int { require (n >= 0, "'n' must be non-negative, but was $n.") // ... } fun require(value: Boolean, message: String) { if (!value) throw IllegalArgumentException(message) }

Slide 3

Slide 3 text

Inline Functions fun nthFibonacciNumber(n: Int): Int { require (n >= 0) { "'n' must be non-negative, but was $n." } // ... } fun require(value: Boolean, lazyMessage: () -> String) { if (!value) throw IllegalArgumentException(lazyMessage()) }

Slide 4

Slide 4 text

Inline Functions fun nthFibonacciNumber(n: Int): Int { require (n >= 0) { "'n' must be non-negative, but was $n." } // ... } inline fun require(value: Boolean, lazyMessage: () -> String) { if (!value) throw IllegalArgumentException(lazyMessage()) }

Slide 5

Slide 5 text

Inline Functions fun nthFibonacciNumber(n: Int): Int { if (!(n >= 0)) throw IllegalArgumentException("'n' must be non-negative, but was $n.") // ... } inline fun require(value: Boolean, lazyMessage: () -> String) { if (!value) throw IllegalArgumentException(lazyMessage()) }

Slide 6

Slide 6 text

Inline Functions. Preconditions // Throws AssertionError inline fun assert(value: Boolean) inline fun assert(value: Boolean, lazyMessage: () -> Any) // Throws IllegalArgumentException inline fun require(value: Boolean) inline fun require(value: Boolean, lazyMessage: () -> Any) inline fun requireNotNull(value: T?): T inline fun requireNotNull(value: T?, lazyMessage: () -> Any): T // Throws IllegalStateException inline fun check(value: Boolean) inline fun check(value: Boolean, lazyMessage: () -> Any) inline fun checkNotNull(value: T?): T inline fun checkNotNull(value: T?, lazyMessage: () -> Any): T // Throws IllegalStateException immediately inline fun error(message: Any)

Slide 7

Slide 7 text

Extension Functions fun String.toInt(): Int = Integer.parseInt(this)

Slide 8

Slide 8 text

Extension Functions fun String.toInt(): Int = Integer.parseInt(this) "42".toInt()

Slide 9

Slide 9 text

Extension Functions fun String.toInt(): Int = Integer.parseInt(this) public static final int toInt(@NotNull String $receiver) { return Integer.parseInt($receiver); }

Slide 10

Slide 10 text

Extension Functions inline fun String.toInt(): Int = Integer.parseInt(this)

Slide 11

Slide 11 text

Extension Functions. Number Conversions inline fun String.toByte(radix: Int = 10): Byte inline fun String.toShort(radix: Int = 10): Short inline fun String.toInt(radix: Int = 10): Int inline fun String.toLong(radix: Int = 10): Long inline fun String.toFloat(): Float inline fun String.toDouble(): Double inline fun String.toBoolean(): Boolean inline fun Byte.toString(radix: Int): String inline fun Short.toString(radix: Int): String inline fun Int.toString(radix: Int): String inline fun Long.toString(radix: Int): String fun String.toByteOrNull(radix: Int = 10): Byte? fun String.toShortOrNull(radix: Int = 10): Short? fun String.toIntOrNull(radix: Int = 10): Int? fun String.toLongOrNull(radix: Int = 10): Long? fun String.toFloatOrNull(): Float? fun String.toDoubleOrNull(): Double?

Slide 12

Slide 12 text

Operator Overloading operator fun plus(other: P): R // a + b, a += b operator fun minus(other: P): R // a - b, a -= b operator fun times(other: P): R // a * b, a *= b operator fun div(other: P): R // a / b, a /= b operator fun rem(other: P): R // a % b, a %= b operator fun plusAssign(other: P): Unit // a += b operator fun minusAssign(other: P): Unit // a -= b operator fun timesAssign(other: P): Unit // a *= b operator fun divAssign(other: P): Unit // a /= b operator fun remAssign(other: P): Unit // a %= b operator fun unaryPlus(): R // +a operator fun unaryMinus(): R // -a operator fun inc(): MyType // a++, ++a operator fun dec(): MyType // a--, --a operator fun not(): R // !a operator fun compareTo(other: P): Int // a >= b, a > b, a < b, a <= b operator fun equals(other: Any?): Boolean // a == b, a != b operator fun contains(other: P): Boolean // b in a, b !in a

Slide 13

Slide 13 text

inline operator fun BigInteger.plus(other: BigInteger) : BigInteger inline operator fun BigInteger.minus(other: BigInteger) : BigInteger inline operator fun BigInteger.times(other: BigInteger) : BigInteger inline operator fun BigInteger.div(other: BigInteger) : BigInteger inline operator fun BigInteger.rem(other: BigInteger) : BigInteger inline operator fun BigInteger.unaryMinus() : BigInteger Operator Overloading. Big Numbers

Slide 14

Slide 14 text

inline operator fun BigInteger.plus(other: BigInteger) : BigInteger inline operator fun BigInteger.minus(other: BigInteger) : BigInteger inline operator fun BigInteger.times(other: BigInteger) : BigInteger inline operator fun BigInteger.div(other: BigInteger) : BigInteger inline operator fun BigInteger.rem(other: BigInteger) : BigInteger inline operator fun BigInteger.unaryMinus() : BigInteger val enormousNumber = BigInteger("12345678909876543210") * BigInteger("42") Operator Overloading. Big Numbers

Slide 15

Slide 15 text

inline operator fun BigInteger.plus(other: BigInteger) : BigInteger inline operator fun BigInteger.minus(other: BigInteger) : BigInteger inline operator fun BigInteger.times(other: BigInteger) : BigInteger inline operator fun BigInteger.div(other: BigInteger) : BigInteger inline operator fun BigInteger.rem(other: BigInteger) : BigInteger inline operator fun BigInteger.unaryMinus() : BigInteger val enormousNumber = BigInteger("12345678909876543210") * BigInteger("42") val enormousNumberV2 = -enormousNumber Operator Overloading. Big Numbers

Slide 16

Slide 16 text

inline operator fun BigInteger.plus(other: BigInteger) : BigInteger inline operator fun BigInteger.minus(other: BigInteger) : BigInteger inline operator fun BigInteger.times(other: BigInteger) : BigInteger inline operator fun BigInteger.div(other: BigInteger) : BigInteger inline operator fun BigInteger.rem(other: BigInteger) : BigInteger inline operator fun BigInteger.unaryMinus() : BigInteger val enormousNumber = BigInteger("12345678909876543210") * BigInteger("42") val enormousNumberV2 = -enormousNumber if (BigInteger("42") > BigInteger.TEN) { println("Welcome, Captain Obvious!") } Operator Overloading. Big Numbers

Slide 17

Slide 17 text

Operator Overloading operator fun invoke(p1: P1, ..., pN: PN): R // a(p1, ..., pN) operator fun get(p1: P1, ..., pN: PN): R // a[p1, ..., pN] operator fun set(p1: P1, ..., pN: PN, t: T): Unit // a[p1, ..., pN] = t operator fun rangeTo(other: P): R // a..b operator fun component1(): R // val myVal = MyType() operator fun componentN(): R // val (c1, ..., cN) = myVal operator fun iterator(): PseudoIterator // val myVal = MyType() // for (i in myVal) { class PseudoIterator { // ... operator fun next(): R // } operator fun hasNext(): Boolean }

Slide 18

Slide 18 text

Operator Overloading operator fun invoke(p1: P1, ..., pN: PN): R // a(p1, ..., pN) operator fun get(p1: P1, ..., pN: PN): R // a[p1, ..., pN] operator fun set(p1: P1, ..., pN: PN, t: T): Unit // a[p1, ..., pN] = t operator fun rangeTo(other: P): R // a..b operator fun component1(): R // val myVal = MyType() operator fun componentN(): R // val (c1, ..., cN) = myVal operator fun iterator(): PseudoIterator // val myVal = MyType() // for (i in myVal) { class PseudoIterator { // ... operator fun next(): R // } operator fun hasNext(): Boolean }

Slide 19

Slide 19 text

Operator Overloading. Iterators for (i in 5432) println(i)

Slide 20

Slide 20 text

Operator Overloading. Iterators for (i in 5432) println(i) operator fun Int.iterator(): MyType = MyType(this)

Slide 21

Slide 21 text

Operator Overloading. Iterators class MyType(private var value: Int) { private var divider: Int init { val pow10 = if (value == 0) 1 else Math.log10(value.toDouble()).toInt() divider = Math.pow(10.0, pow10.toDouble()).toInt() } operator fun next(): Int { val res = value / divider value %= divider divider /= 10 return res } operator fun hasNext() = divider > 0 }

Slide 22

Slide 22 text

Operator Overloading. Iterators for (i in 5432) println(i) // 5, 4, 3, 2

Slide 23

Slide 23 text

Function Literals with Receiver Map headers = new ArrayMap() {{ this.put("User-Agent", userAgent); if (userManager.isLoggedIn) { this.put("Authorization", userManager.accessToken); } }};

Slide 24

Slide 24 text

Function Literals with Receiver inline fun T.apply(block: T.() -> Unit): T { this.block(); return this } val headers = ArrayMap().apply { this.put("User-Agent", userAgent) if (userManager.isLoggedIn) { this.put("Authorization", userManager.accessToken) } }

Slide 25

Slide 25 text

Function Literals with Receiver inline fun T.apply(block: T.() -> Unit): T { this.block(); return this } val headers = ArrayMap().apply { put("User-Agent", userAgent) if (userManager.isLoggedIn) { put("Authorization", userManager.accessToken) } }

Slide 26

Slide 26 text

var user: User? fun renderUser() { if (user != null) { nameView.text = user.name ageView.text = user.age } } Function Literals with Receiver

Slide 27

Slide 27 text

var user: User? fun renderUser() { if (user != null) { nameView.text = user.name ageView.text = user.age } } Error! Smart cast to ‘User’ is impossible, because ‘user’ is a mutable property that could have been changed by this time. Function Literals with Receiver

Slide 28

Slide 28 text

var user: User? fun renderUser() { val usr = user if (usr != null) { nameView.text = usr.name ageView.text = usr.age } } Function Literals with Receiver

Slide 29

Slide 29 text

inline fun T.let(block: (T) -> R): R = block(this) var user: User? fun renderUser() { val usr = user if (usr != null) { nameView.text = usr.name ageView.text = usr.age } } Function Literals with Receiver

Slide 30

Slide 30 text

inline fun T.let(block: (T) -> R): R = block(this) var user: User? fun renderUser() { user?.let { usr -> nameView.text = usr.name ageView.text = usr.age } } Function Literals with Receiver

Slide 31

Slide 31 text

inline fun T.let(block: (T) -> R): R = block(this) var user: User? fun renderUser() { user?.let { nameView.text = it.name ageView.text = it.age } } Function Literals with Receiver

Slide 32

Slide 32 text

inline fun T.let(block: (T) -> R): R = block(this) var user: User? fun renderUser() { user?.let { // ‘user’ is not null nameView.text = it.name ageView.text = it.age } } Function Literals with Receiver

Slide 33

Slide 33 text

inline fun T.let(block: (T) -> R): R = block(this) var user: User? fun renderUser() { user?.let { // ‘user’ is not null and nameView.text = it.name ageView.text = it.age } } Function Literals with Receiver

Slide 34

Slide 34 text

inline fun T.let(block: (T) -> R): R = block(this) var user: User? fun renderUser() { user?.let { // ‘user’ is not null and it was already read into local val nameView.text = it.name ageView.text = it.age } } Function Literals with Receiver

Slide 35

Slide 35 text

Function Literals with Receiver inline fun T.let(block: (T) -> R): R = block(this) fun fetchData() { getResponse()?.let { // result of ‘getResponse()’ was already read/delivered/calculated logResponse(it) saveData(parseData(it)) } }

Slide 36

Slide 36 text

Function Literals with Receiver inline fun T.apply(block: T.() -> Unit): T { block(); return this } inline fun T.also(block: (T) -> Unit): T { block(this); return this } inline fun with(receiver: T, block: T.() -> R): R = receiver.block() inline fun T.let(block: (T) -> R): R = block(this) inline fun T.run(block: T.() -> R): R = block() inline fun run(block: () -> R): R = block()

Slide 37

Slide 37 text

Reified Type Parameters Map int2Str = new HashMap();

Slide 38

Slide 38 text

Reified Type Parameters Map int2Str = newMap(); Map newMap() { return new HashMap(); }

Slide 39

Slide 39 text

Reified Type Parameters Map int2Str = newMap(); Map newMap() { return new HashMap(); } String[] strArr = newArray(42) T[] newArray(int size) { return new T[size]; }

Slide 40

Slide 40 text

Reified Type Parameters Map int2Str = newMap(); Map newMap() { return new HashMap(); } String[] strArr = newArray(42) T[] newArray(int size) { return new T[size]; }

Slide 41

Slide 41 text

Reified Type Parameters fun arrayOfNulls(size: Int): Array = T[size]

Slide 42

Slide 42 text

Reified Type Parameters inline fun arrayOfNulls(size: Int): Array = T[size]

Slide 43

Slide 43 text

Reified Type Parameters inline fun arrayOfNulls(size: Int): Array = T[size]

Slide 44

Slide 44 text

Reified Type Parameters inline fun arrayOfNulls(size: Int): Array = T[size] fun fill(dest: Array) { // ... } fill(arrayOfNulls(10))

Slide 45

Slide 45 text

Reified Type Parameters. Arrays inline fun arrayOfNulls(size: Int): Array // = T[size] inline fun arrayOf(vararg elements: T): Array // = T[] { elements } inline fun emptyArray(): Array // = T[0]

Slide 46

Slide 46 text

Kotlin features Stdlib is based on ● Inline Functions ● Extension Functions ● Operator Overloading ● Function Literals with Receiver ● Reified type parameters

Slide 47

Slide 47 text

Collections fun emptyList(): List = EmptyList fun listOf(element: T): List = Collections.singletonList(element) fun listOf([vararg elements: T]): List fun mutableListOf([vararg elements: T]): MutableList // ArrayList fun arrayListOf([vararg elements: T]): ArrayList fun listOfNotNull(element: T?): List fun listOfNotNull(vararg elements: T?): List inline fun List(size: Int, init: (index: Int) -> T): List inline fun MutableList(size: Int, init: (index: Int) -> T): MutableList

Slide 48

Slide 48 text

fun emptySet(): Set = EmptySet fun setOf(element: T): Set = Collections.singleton(element) fun setOf([vararg elements: T]): Set fun mutableSetOf([vararg elements: T]): MutableSet // LinkedHashSet fun hashSetOf([vararg elements: T]): HashSet fun linkedSetOf([vararg elements: T]): LinkedHashSet fun sortedSetOf([comparator: Comparator,] vararg elements: T): TreeSet Collections

Slide 49

Slide 49 text

Collections val List.lastIndex: Int get() = this.size - 1 inline fun Collection?.orEmpty(): Collection inline fun List?.orEmpty(): List

Slide 50

Slide 50 text

Collections inline operator fun List.component1(): T inline operator fun List.component5(): T operator fun Iterable.contains(element: T): Boolean operator fun Collection.plus(T|Array|Iterable|Sequence): List operator fun Iterable.plus(T|Array|Iterable|Sequence): List operator fun Iterable.minus(T|Array|Iterable|Sequence): List

Slide 51

Slide 51 text

Collections inline operator fun List.component1(): T inline operator fun List.component5(): T operator fun Iterable.contains(element: T): Boolean operator fun Collection.plus(T|Array|Iterable|Sequence): List operator fun Iterable.plus(T|Array|Iterable|Sequence): List operator fun Iterable.minus(T|Array|Iterable|Sequence): List val (s1, s2, s3, s4, s5) = listOf(...)

Slide 52

Slide 52 text

Collections inline operator fun List.component1(): T inline operator fun List.component5(): T operator fun Iterable.contains(element: T): Boolean operator fun Collection.plus(T|Array|Iterable|Sequence): List operator fun Iterable.plus(T|Array|Iterable|Sequence): List operator fun Iterable.minus(T|Array|Iterable|Sequence): List if ("Jan" in months) { // ... }

Slide 53

Slide 53 text

Collections inline operator fun List.component1(): T inline operator fun List.component5(): T operator fun Iterable.contains(element: T): Boolean operator fun Collection.plus(T|Array|Iterable|Sequence): List operator fun Iterable.plus(T|Array|Iterable|Sequence): List operator fun Iterable.minus(T|Array|Iterable|Sequence): List androidLanguagesList += "Kotlin"

Slide 54

Slide 54 text

Collections. Search inline fun Iterable.first([predicate: (T) -> Boolean]): T inline fun Iterable.last([predicate: (T) -> Boolean]): T inline fun Iterable.firstOrNull([predicate: (T) -> Boolean]): T? inline fun Iterable.lastOrNull([predicate: (T) -> Boolean]): T? inline fun Iterable.find(predicate: (T) -> Boolean): T? // = firstOrNull() inline fun Iterable.findLast(predicate: (T) -> Boolean): T? // = lastOrNull() inline fun Iterable.single([predicate: (T) -> Boolean]): T inline fun Iterable.singleOrNull([predicate: (T) -> Boolean]): T

Slide 55

Slide 55 text

Collections. Search fun Iterable.indexOf(element: T): Int fun Iterable.lastIndexOf(element: T): Int inline fun Iterable.indexOfFirst(predicate: (T) -> Boolean): Int inline fun Iterable.indexOfLast(predicate: (T) -> Boolean): Int fun List.binarySearch([from: Int, to: Int,] comparison: (T) -> Int): Int fun > List.binarySearch(elem: T?, [from: Int, to: Int]): Int fun List. binarySearch(elem: T, comparator: Comparator, [from: Int, to: Int]): Int inline fun > List. binarySearchBy(key: K?, [from: Int, to: Int,] selector: (T) -> K?): Int

Slide 56

Slide 56 text

Collections. Filtering inline fun Iterable.filter(predicate: (T) -> Boolean): List inline fun Iterable.filterIndexed(predicate: (index: Int, T) -> Boolean): List inline fun Iterable.filterNot(predicate: (T) -> Boolean): List fun Iterable.filterNotNull(): List inline fun > Iterable. filterTo(dest: C, predicate: (T) -> Boolean): C filterIndexedTo(dest: C, predicate: (index: Int, T) -> Boolean): C filterNotTo(dest: C, predicate: (T) -> Boolean): C fun , T : Any> Iterable.filterNotNullTo(dest: C): C fun Iterable<*>.filterIsInstance(klass: Class): List inline fun Iterable<*>.filterIsInstance(): List fun , R> Iterable<*>. filterIsInstanceTo(dest: C, klass: Class): C inline fun > Iterable<*>. filterIsInstanceTo(dest: C): C

Slide 57

Slide 57 text

Collections. Filtering fun MutableIterable.removeAll(cond: (T) -> Boolean): Boolean // filterNotInPlace() fun MutableIterable.retainAll(cond: (T) -> Boolean): Boolean // filterInPlace() fun MutableCollection.removeAll(Array|Iterable|Sequence): Boolean fun MutableCollection.retainAll(Array|Iterable|Sequence): Boolean

Slide 58

Slide 58 text

Collections. Filtering fun Iterable.take(n: Int): List fun List.takeLast(n: Int): List inline fun Iterable.takeWhile(predicate: (T) -> Boolean): List inline fun List.takeLastWhile(predicate: (T) -> Boolean): List fun Iterable.drop(n: Int): List fun List.dropLast(n: Int): List inline fun Iterable.dropWhile(predicate: (T) -> Boolean): List inline fun List.dropLastWhile(predicate: (T) -> Boolean): List

Slide 59

Slide 59 text

Collections. Sorting fun > Iterable.sorted(): List fun > Iterable.sortedDescending(): List fun > MutableList.sort(): Unit fun > MutableList.sortDescending(): Unit inline fun > Iterable.sortedBy(selector: (T) -> R?): List inline fun > Iterable.sortedByDescending(selector: (T) -> R?): List inline fun > MutableList.sortBy(selector: (T) -> R?): Unit inline fun > MutableList.sortByDescending(selector: (T) -> R?): Unit fun Iterable.sortedWith(comparator: Comparator): List fun MutableList.sortWith(comparator: Comparator): Unit

Slide 60

Slide 60 text

Collections. Reversing & Slicing fun Iterable.reversed(): List fun MutableList.reverse(): Unit fun List.asReversed(): List fun MutableList.asReversed(): MutableList fun List.slice(indices: IntRange): List fun List.slice(indices: Iterable): List

Slide 61

Slide 61 text

Collections. Mapping inline fun Iterable. associate(transform: (T) -> Pair): Map associateBy(keySelector: (T) -> K, [valueTransform: (T) -> V]): Map inline fun > Iterable. associateTo(dest: M, transform: (T) -> Pair): M associateByTo(dest: M, keySelector: (T) -> K, [valueTransform: (T) -> V]): M

Slide 62

Slide 62 text

Collections. Mapping inline fun Iterable. map(transform: (T) -> R): List mapIndexed(transform: (index: Int, T) -> R): List inline fun Iterable. mapNotNull(transform: (T) -> R?): List mapIndexedNotNull(transform: (index: Int, T) -> R?): List inline fun > Iterable. mapTo(dest: C, transform: (T) -> R): C mapIndexedTo(dest: C, transform: (index: Int, T) -> R): C inline fun > Iterable. mapNotNullTo(dest: C, transform: (T) -> R?): C mapIndexedNotNullTo(dest: C, transform: (index: Int, T) -> R?): C

Slide 63

Slide 63 text

Collections. Mapping & Grouping inline fun Iterable.forEach(action: (T) -> Unit): Unit inline fun Iterable.forEachIndexed(action: (index: Int, T) -> Unit): Unit inline fun > C.onEach(action: (T) -> Unit): C inline fun Iterable.flatMap(transform: (T) -> Iterable): List inline fun > Iterable. flatMapTo(dest: C, transform: (T) -> Iterable): C inline fun Iterable. groupBy(keySelector: (T) -> K, [valueTransform: (T) -> V]): Map> inline fun >> Iterable. groupByTo(dest: M, keySelector: (T) -> K, [valueTransform: (T) -> V]): M inline fun Iterable.groupingBy(keySelector: (T) -> K): Grouping

Slide 64

Slide 64 text

Collections. Misc fun Iterable.distinct(): List inline fun Iterable.distinctBy(selector: (T) -> K): List fun Iterable>.flatten(): List infix fun Iterable.zip(Array|Iterable): List> inline fun Iterable. zip(Array|Iterable, transform: (a: T, b: R) -> V): List fun Iterable>.unzip(): Pair, List> inline fun Iterable.partition(predicate: (T) -> Boolean): Pair, List> infix fun Iterable.intersect(other: Iterable): Set infix fun Iterable.subtract(other: Iterable): Set infix fun Iterable.union(other: Iterable): Set

Slide 65

Slide 65 text

Collections. Aggregation fun Iterable.average(): Double fun Iterable.sum(): Int inline fun Iterable.sumBy(selector: (T) -> Int): Int inline fun Iterable.sumByDouble(selector: (T) -> Double): Double inline fun Iterable.count([predicate: (T) -> Boolean]): Int fun > Iterable.max(): T? fun > Iterable.min(): T? inline fun > Iterable.maxBy(selector: (T) -> R): T? inline fun > Iterable.minBy(selector: (T) -> R): T? fun Iterable.maxWith(comparator: Comparator): T? fun Iterable.minWith(comparator: Comparator): T? inline fun Iterable.all(predicate: (T) -> Boolean): Boolean inline fun Iterable.any([predicate: (T) -> Boolean]): Boolean inline fun Iterable.none([predicate: (T) -> Boolean]): Boolean

Slide 66

Slide 66 text

Collections. Folding & Reducing inline fun Iterable. fold(initial: R, operation: (acc: R, T) -> R): R foldIndexed(initial: R, operation: (index: Int, acc: R, T) -> R): R inline fun List. foldRight(initial: R, operation: (T, acc: R) -> R): R foldRightIndexed(initial: R, operation: (index: Int, T, acc: R) -> R): R inline fun Iterable. reduce(operation: (acc: S, T) -> S): S reduceIndexed(operation: (index: Int, acc: S, T) -> S): S inline fun List. reduceRight(operation: (T, acc: S) -> S): S reduceRightIndexed(operation: (index: Int, T, acc: S) -> S): S

Slide 67

Slide 67 text

Collections. ToString fun Iterable.joinToString( separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): String fun Iterable.joinTo( buffer: A, sep: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): A

Slide 68

Slide 68 text

Collections. FTW!

Slide 69

Slide 69 text

Here goes all the same stuff for Arrays, Sequences and CharSequences... ...if applicable

Slide 70

Slide 70 text

Collections. Conversion fun > Iterable.toCollection(dest: C): C fun Iterable.toList(): List fun Iterable.toMutableList(): MutableList fun Iterable.toSet(): Set fun Iterable.toMutableSet(): MutableSet fun Iterable.toHashSet(): HashSet fun > Iterable.toSortedSet([comparator: Comparator]): SortedSet inline fun Collection.toTypedArray(): Array inline fun Iterable.asIterable(): Iterable fun Iterable.asSequence(): Sequence

Slide 71

Slide 71 text

Collections. Conversion fun > Iterable.toCollection(dest: C): C fun Iterable.toList(): List fun Iterable.toMutableList(): MutableList fun Iterable.toSet(): Set fun Iterable.toMutableSet(): MutableSet fun Iterable.toHashSet(): HashSet fun > Iterable.toSortedSet([comparator: Comparator]): SortedSet inline fun Collection.toTypedArray(): Array inline fun Iterable.asIterable(): Iterable fun Iterable.asSequence(): Sequence

Slide 72

Slide 72 text

Collections. Conversion fun > Iterable.toCollection(dest: C): C fun Iterable.toList(): List fun Iterable.toMutableList(): MutableList fun Iterable.toSet(): Set fun Iterable.toMutableSet(): MutableSet fun Iterable.toHashSet(): HashSet fun > Iterable.toSortedSet([comparator: Comparator]): SortedSet inline fun Collection.toTypedArray(): Array inline fun Iterable.asIterable(): Iterable fun Iterable.asSequence(): Sequence

Slide 73

Slide 73 text

data class User(val birthday: Date, val movies: List) data class Movie(val title: String, val airDate: Date, val posterUrl: String, val likesCount: Int, val genre: Genre) Collections

Slide 74

Slide 74 text

data class User(val birthday: Date, val movies: List) data class Movie(val title: String, val airDate: Date, val posterUrl: String, val likesCount: Int, val genre: Genre) repo.getMovies() Collections

Slide 75

Slide 75 text

data class User(val birthday: Date, val movies: List) data class Movie(val title: String, val airDate: Date, val posterUrl: String, val likesCount: Int, val genre: Genre) repo.getMovies() .filter { it.airDate > user.birthday } Collections

Slide 76

Slide 76 text

data class User(val birthday: Date, val movies: List) data class Movie(val title: String, val airDate: Date, val posterUrl: String, val likesCount: Int, val genre: Genre) repo.getMovies() .filter { it.airDate > user.birthday } .filter { it.title in user.movies } Collections

Slide 77

Slide 77 text

data class User(val birthday: Date, val movies: List) data class Movie(val title: String, val airDate: Date, val posterUrl: String, val likesCount: Int, val genre: Genre) repo.getMovies() .filter { it.airDate > user.birthday } .filter { it.title in user.movies } .groupBy { it.genre } Collections

Slide 78

Slide 78 text

data class User(val birthday: Date, val movies: List) data class Movie(val title: String, val airDate: Date, val posterUrl: String, val likesCount: Int, val genre: Genre) repo.getMovies() .filter { it.airDate > user.birthday } .filter { it.title in user.movies } .groupBy { it.genre } .map { (genre, movies) -> Triple(genre, movies.size, movies.maxBy { it.likesCount }) } Collections

Slide 79

Slide 79 text

data class User(val birthday: Date, val movies: List) data class Movie(val title: String, val airDate: Date, val posterUrl: String, val likesCount: Int, val genre: Genre) repo.getMovies() .filter { it.airDate > user.birthday } .filter { it.title in user.movies } .groupBy { it.genre } .map { (genre, movies) -> Triple(genre, movies.size, movies.maxBy { it.likesCount }) } .sortedByDescending { (_, count, _) -> count } Collections

Slide 80

Slide 80 text

data class User(val birthday: Date, val movies: List) data class Movie(val title: String, val airDate: Date, val posterUrl: String, val likesCount: Int, val genre: Genre) repo.getMovies() .filter { it.airDate > user.birthday } .filter { it.title in user.movies } .groupBy { it.genre } .map { (genre, movies) -> Triple(genre, movies.size, movies.maxBy { it.likesCount }) } .sortedByDescending { (_, count, _) -> count } .forEach { (genre, count, movie) -> plotHistogram(label = genre, value = count, tooltipImageUrl = movie?.posterUrl) } Collections

Slide 81

Slide 81 text

repo.getMovies() .filter { it.airDate > user.birthday } .filter { it.title in user.movies } .groupBy { it.genre } .map { (genre, movies) -> Triple(genre, movies.size, movies.maxBy { it.likesCount }) } .sortedByDescending { (_, count, _) -> count } .forEach { (genre, count, movie) -> plotHistogram(label = genre, value = count, tooltipImageUrl = movie?.posterUrl) } Collections

Slide 82

Slide 82 text

repo.getMovies() .filter { it.airDate > user.birthday } .filter { it.title in user.movies } .groupBy { it.genre } .map { (genre, movies) -> Triple(genre, movies.size, movies.maxBy { it.likesCount }) } .sortedByDescending { (_, count, _) -> count } .joinToString(separator = "\n", prefix = "My movie preferences by genre:\n") { (genre, count, _) -> "$genre movies watched: $count" } Collections

Slide 83

Slide 83 text

fun emptySequence(): Sequence = EmptySequence fun sequenceOf(vararg elements: T): Sequence fun generateSequence(nextFunction: () -> T?): Sequence generateSequence(seed: T?, nextFunction: (T) -> T?): Sequence generateSequence(seedFunction: () -> T?, nextFunction: (T) -> T?): Sequence inline fun Sequence(iterator: () -> Iterator): Sequence fun Sequence.constrainOnce(): Sequence Sequences

Slide 84

Slide 84 text

fun genFibonacciSequence(): Sequence = generateSequence(0 to 1) { (prev, next) -> next to (prev + next) }.map { (next, _) -> next } Sequences

Slide 85

Slide 85 text

fun genFibonacciSequence(): Sequence = generateSequence(0 to 1) { (prev, next) -> next to (prev + next) }.map { (next, _) -> next } genFibonacciSequence() .takeWhile { it < 100 } .forEach(::println) Sequences

Slide 86

Slide 86 text

fun genFibonacciSequence(): Sequence = generateSequence(0 to 1) { (prev, next) -> next to (prev + next) }.map { (next, _) -> next } genFibonacciSequence() .takeWhile { it < 100 } .forEach(::println) // 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 Sequences

Slide 87

Slide 87 text

repo.getMovies() .filter { it.airDate > user.birthday } .filter { it.title in user.movies } .groupBy { it.genre } .map { (genre, movies) -> Triple(genre, movies.size, movies.maxBy { it.likesCount }) } .sortedByDescending { (_, count, _) -> count } .forEach { (genre, count, movie) -> plotHistogram(label = genre, value = count, tooltipImageUrl = movie?.posterUrl) } Sequences

Slide 88

Slide 88 text

repo.getMovies() .filter { it.airDate > user.birthday } .filter { it.title in user.movies } .groupBy { it.genre } .map { (genre, movies) -> Triple(genre, movies.size, movies.maxBy { it.likesCount }) } .sortedByDescending { (_, count, _) -> count } .forEach { (genre, count, movie) -> plotHistogram(label = genre, value = count, tooltipImageUrl = movie?.posterUrl) } Sequences

Slide 89

Slide 89 text

repo.getMovies() .asSequence() .filter { it.airDate > user.birthday } .filter { it.title in user.movies } .groupBy { it.genre } .asSequence() .map { (genre, movies) -> Triple(genre, movies.size, movies.maxBy { it.likesCount }) } .sortedByDescending { (_, count, _) -> count } .forEach { (genre, count, movie) -> plotHistogram(label = genre, value = count, tooltipImageUrl = movie?.posterUrl) } Sequences

Slide 90

Slide 90 text

repo.getMovies() .asSequence() .filter { it.airDate > user.birthday } .filter { it.title in user.movies } .groupBy { it.genre } .asSequence() .map { (genre, movies) -> Triple(genre, movies.size, movies.maxBy { it.likesCount }) } .sortedByDescending { (_, count, _) -> count } .forEach { (genre, count, movie) -> plotHistogram(label = genre, value = count, tooltipImageUrl = movie?.posterUrl) } Sequences

Slide 91

Slide 91 text

fun emptyMap(): Map = EmptyMap fun mapOf(p: Pair): Map = Collections.singletonMap(p.first, p.second) fun mapOf([vararg pairs: Pair]): Map fun mutableMapOf([vararg pairs: Pair]): MutableMap // LinkedHashMap fun hashMapOf([vararg pairs: Pair]): HashMap fun linkedMapOf([vararg pairs: Pair]): LinkedHashMap fun , V> sortedMapOf(vararg pairs: Pair): SortedMap inline fun Map.getOrElse(key: K, defaultValue: () -> V): V inline fun MutableMap.getOrPut(key: K, defaultValue: () -> V): V Maps

Slide 92

Slide 92 text

fun emptyMap(): Map = EmptyMap fun mapOf(p: Pair): Map = Collections.singletonMap(p.first, p.second) fun mapOf([vararg pairs: Pair]): Map fun mutableMapOf([vararg pairs: Pair]): MutableMap // LinkedHashMap fun hashMapOf([vararg pairs: Pair]): HashMap fun linkedMapOf([vararg pairs: Pair]): LinkedHashMap fun , V> sortedMapOf(vararg pairs: Pair): SortedMap inline fun Map.getOrElse(key: K, defaultValue: () -> V): V inline fun MutableMap.getOrPut(key: K, defaultValue: () -> V): V Maps

Slide 93

Slide 93 text

inline fun Map. filterKeys(predicate: (K) -> Boolean): Map filterValues(predicate: (V) -> Boolean): Map inline fun Map. mapKeys(transform: (Map.Entry) -> R): Map mapValues(transform: (Map.Entry) -> R): Map Maps. Extra

Slide 94

Slide 94 text

Maps fun wordCount(list: List): Map { val map = mutableMapOf() for (item in list) { if (item !in map) { map[item] = 0 } map[item] = map[item] + 1 } return map }

Slide 95

Slide 95 text

Maps fun wordCount(list: List): Map { val map = mutableMapOf() for (item in list) { if (item !in map) { map[item] = 0 } map[item] = map[item] + 1 } return map } Error! Operator plus is not allowed on a nullable receiver.

Slide 96

Slide 96 text

Maps fun wordCount(list: List): Map { val map = mutableMapOf() for (item in list) { if (item !in map) { map[item] = 0 } map[item] = map[item]!! + 1 } return map }

Slide 97

Slide 97 text

Maps fun wordCount(list: List): Map { val map = mutableMapOf() for (item in list) { map[item] = (map[item] ?: 0) + 1 } return map }

Slide 98

Slide 98 text

Maps fun wordCount(list: List): Map { val map = mutableMapOf() for (item in list) { map[item] = map.getOrElse(item) { 0 } + 1 } return map }

Slide 99

Slide 99 text

Maps with Default fun Map.withDefault(defaultValue: (key: K) -> V): Map Warning! Does not change Map.get() semantics! Use Map.getValue() fun Map.getValue(key: K): V

Slide 100

Slide 100 text

Maps with Default fun wordCount(list: List): Map { val map = mutableMapOf().withDefault { 0 } for (item in list) { map[item] = map.getValue(item) + 1 } return map }

Slide 101

Slide 101 text

inline fun Iterable.groupingBy(keySelector: (T) -> K): Grouping Grouping

Slide 102

Slide 102 text

inline fun Iterable.groupingBy(keySelector: (T) -> K): Grouping interface Grouping { fun sourceIterator(): Iterator fun keyOf(element: T): K } Grouping

Slide 103

Slide 103 text

Grouping inline fun Iterable.groupingBy(keySelector: (T) -> K): Grouping interface Grouping { fun sourceIterator(): Iterator fun keyOf(element: T): K } inline fun Grouping. aggregate(op: (key: K, accumulator: R?, elem: T, first: Boolean) -> R): Map

Slide 104

Slide 104 text

Grouping fun wordCount(list: List): Map { return list .groupingBy { word -> word } .aggregate { key, acc, elem, first -> (acc ?: 0) + 1 } }

Slide 105

Slide 105 text

Grouping fun wordCount(list: List): Map = list.groupingBy { it } .aggregate { _, acc, _, _ -> (acc ?: 0) + 1 }

Slide 106

Slide 106 text

Grouping fun wordCount(list: List): Map = list.groupingBy { it } .aggregate { _, acc, _, _ -> (acc ?: 0) + 1 } fun Grouping.eachCount(): Map

Slide 107

Slide 107 text

Grouping fun wordCount(list: List): Map = list.groupingBy { it }.eachCount() fun Grouping.eachCount(): Map

Slide 108

Slide 108 text

Grouping fun wordCount(list: List): Map = list.groupingBy { it }.eachCount() fun wordCount(list: List): Map { val map = mutableMapOf() for (item in list) { if (item !in map) { map[item] = 0 } map[item] = map[item]!! + 1 } return map }

Slide 109

Slide 109 text

Grouping inline fun Grouping. fold(initialValue: R, operation: (accumulator: R, element: T) -> R): Map fold(initialValueSelector: (key: K, element: T) -> R, operation: (key: K, accumulator: R, element: T) -> R): Map inline fun Grouping. reduce(operation: (key: K, accumulator: S, element: T) -> S): Map

Slide 110

Slide 110 text

Comparisons fun > maxOf(a: T, b: T, [c: T]): T fun > minOf(a: T, b: T, [c: T]): T // + variants for primitive numbers inline fun > nullsFirst(): Comparator inline fun > nullsLast(): Comparator fun nullsFirst(comparator: Comparator): Comparator fun nullsLast(comparator: Comparator): Comparator fun > naturalOrder(): Comparator fun > reverseOrder(): Comparator fun Comparator.reversed(): Comparator

Slide 111

Slide 111 text

Comparisons fun compareBy(vararg selectors: (T) -> Comparable<*>?): Comparator inline fun compareBy(selector: (T) -> Comparable<*>?): Comparator inline fun compareBy(Comparator, selector: (T) -> K): Comparator

Slide 112

Slide 112 text

Comparisons inline fun Comparator. thenComparator(comparison: (a: T, b: T) -> Int): Comparator thenBy(selector: (T) -> Comparable<*>?): Comparator thenByDescending(selector: (T) -> Comparable<*>?): Comparator inline fun Comparator. thenBy(Comparator, selector: (T) -> K): Comparator thenByDescending(Comparator, selector: (T) -> K): Comparator infix fun Comparator. then(comparator: Comparator): Comparator thenDescending(comparator: Comparator): Comparator

Slide 113

Slide 113 text

Comparisons data class Movie(val title: String, val airYear: Int, val posterUrl: String, val likesCount: Int, val genre: Genre, val actors: List) enum class Genre { COMEDY, ACTION, DRAMA, DOCUMENTARY } getMovies() .sortedWith(movieComparator) .filterNot { it.title in user.movies } .take(100)

Slide 114

Slide 114 text

Comparisons val movieComparator = compareBy()

Slide 115

Slide 115 text

Comparisons val movieComparator = compareBy({ it.airYear })

Slide 116

Slide 116 text

Comparisons val movieComparator = compareBy({ it.airYear }, { it.likesCount })

Slide 117

Slide 117 text

Comparisons val movieComparator = compareBy(Movie::airYear, Movie::likesCount)

Slide 118

Slide 118 text

Comparisons val movieComparator = compareBy(Movie::airYear, Movie::likesCount) .thenByDescending { it.actors.size }

Slide 119

Slide 119 text

Comparisons val movieComparator = compareBy(Movie::airYear) .thenBy(Movie::likesCount) .thenByDescending { it.actors.size }

Slide 120

Slide 120 text

Comparisons val movieComparator = compareBy(Movie::airYear) .thenBy(Movie::likesCount) .thenByDescending { it.actors.size } val genreComparator = compareBy { when (it) { Genre.ACTION -> 40 Genre.DOCUMENTARY -> 30 Genre.COMEDY -> 20 Genre.DRAMA -> 10 } }

Slide 121

Slide 121 text

Comparisons val movieComparator = compareBy(Movie::airYear) .thenBy(genreComparator) { it.genre } .thenBy(Movie::likesCount) .thenByDescending { it.actors.size } val genreComparator = compareBy { when (it) { Genre.ACTION -> 40 Genre.DOCUMENTARY -> 30 Genre.COMEDY -> 20 Genre.DRAMA -> 10 } }

Slide 122

Slide 122 text

Comparisons val movieComparator = compareBy(Movie::airYear) .thenBy(genreComparator) { it.genre } .thenBy(Movie::likesCount) .thenByDescending { it.actors.size } .reversed() val genreComparator = compareBy { when (it) { Genre.ACTION -> 40 Genre.DOCUMENTARY -> 30 Genre.COMEDY -> 20 Genre.DRAMA -> 10 } }

Slide 123

Slide 123 text

Text fun String.capitalize(): String fun String.decapitalize(): String fun CharSequence.isBlank(): Boolean inline fun CharSequence?.isNullOrBlank(): Boolean inline fun CharSequence?.isNullOrEmpty(): Boolean // Farewell TextUtils.isEmpty() fun CharSequence. commonPrefixWith(other: CharSequence, [ignoreCase: Boolean]): String commonSuffixWith(other: CharSequence, [ignoreCase: Boolean]): String splitToSequence(vararg delimiters: String, [ignoreCase: Boolean, limit: Int]): Sequence fun CharSequence.lineSequence(): Sequence

Slide 124

Slide 124 text

IO. Closeable inline fun T.use(block: (T) -> R): R inline fun T.use(block: (T) -> R): R

Slide 125

Slide 125 text

IO. Closeable inline fun T.use(block: (T) -> R): R inline fun T.use(block: (T) -> R): R fun InputStream.readLines(): List = BufferedReader(InputStreamReader(this)).use { val lines = arrayListOf() var line = it.readLine() while (line != null) { lines += line line = it.readLine() } lines }

Slide 126

Slide 126 text

IO. Byte Streams inline fun InputStream. buffered([bufferSize: Int]): BufferedInputStream reader([charset: Charset]): InputStreamReader bufferedReader([charset: Charset]): BufferedReader inline fun OutputStream. buffered([bufferSize: Int]): BufferedOutputStream writer([charset: Charset]): OutputStreamWriter bufferedWriter([charset: Charset]): BufferedWriter fun InputStream.copyTo(out: OutputStream, [bufferSize: Int]): Long

Slide 127

Slide 127 text

inline fun Reader.buffered([bufferSize: Int]): BufferedReader inline fun Writer.buffered([bufferSize: Int]): BufferedWriter fun Reader.readText(): String fun Reader.readLines(): List fun BufferedReader.lineSequence(): Sequence inline fun Reader.useLines(block: (Sequence) -> T): T fun Reader.forEachLine(action: (String) -> Unit): Unit fun Reader.copyTo(out: Writer, [bufferSize: Int]): Long IO. Text Streams

Slide 128

Slide 128 text

IO. Files inline fun File.inputStream(): FileInputStream inline fun File.outputStream(): FileOutputStream inline fun File.reader([charset: Charset]): InputStreamReader inline fun File.writer([charset: Charset]): OutputStreamWriter inline fun File.bufferedReader([charset: Charset, bufferSize: Int]): BufferedReader inline fun File.bufferedWriter([charset: Charset, bufferSize: Int]): BufferedWriter inline fun File.printWriter([charset: Charset]): PrintWriter

Slide 129

Slide 129 text

IO. Files fun File.readBytes(): ByteArray fun File.writeBytes(array: ByteArray): Unit fun File.appendBytes(array: ByteArray): Unit fun File.readText([charset: Charset]): String fun File.writeText(text: String, [charset: Charset]): Unit fun File.appendText(text: String, [charset: Charset]): Unit fun File.readLines([charset: Charset]): List inline fun File.useLines([charset: Charset], block: (Sequence) -> T): T fun File.forEachLine([charset: Charset], action: (String) -> Unit): Unit fun File.forEachBlock([blockSize: Int,] action: (buffer: ByteArray, bytesRead: Int) -> Unit): Unit

Slide 130

Slide 130 text

IO. Files val wordCount = File("shakespeare.txt").useLines { it.flatMap { it.splitToSequence(' ', ',', '.', '!', '?') } .map { it.toLowerCase() } .groupingBy { it } .eachCount() }

Slide 131

Slide 131 text

IO. Files val wordCount = File("shakespeare.txt").useLines { it.flatMap { it.splitToSequence(' ', ',', '.', '!', '?') } .map { it.toLowerCase() } .groupingBy { it } .eachCount() }

Slide 132

Slide 132 text

IO. Files val wordCount = File("shakespeare.txt").bufferedReader().use { it.lineSequence().flatMap { it.splitToSequence(' ', ',', '.', '!', '?') } .map { it.toLowerCase() } .groupingBy { it } .eachCount() }

Slide 133

Slide 133 text

IO. Files val File.extension: String val File.invariantSeparatorsPath: String val File.nameWithoutExtension: String fun File.toRelativeString(base: File): String fun File.relativeTo(base: File): File fun File.relativeToOrSelf(base: File): File fun File.relativeToOrNull(base: File): File? fun File.resolve(relative: String|File): File fun File.resolveSibling(relative: String|File): File fun File.startsWith(other: String|File): Boolean fun File.endsWith(other: String|File): Boolean

Slide 134

Slide 134 text

IO. Files fun createTempDir(prefix: String = "tmp", [suffix: String?, directory: File?]): File fun createTempFile(prefix: String = "tmp", [suffix: String?, directory: File?]): File fun File.copyTo(target: File, overwrite: Boolean = false, [bufferSize: Int]): File fun File.copyRecursively(target: File, overwrite: Boolean = false, [onError: (File, IOException) -> OnErrorAction]): Boolean fun File.deleteRecursively(): Boolean

Slide 135

Slide 135 text

Goodies. Ranges fun processResponse(response: Response) = when (response.code) { in 200..299 -> ok(response) in 400..499 -> clientError(response) in 500..599 -> serverError(response) else -> throw IllegalStateException("Bummer")

Slide 136

Slide 136 text

Goodies. Ranges fun processResponse(response: Response) = when (response.code) { in 200..299 -> ok(response) in 400..499 -> clientError(response) in 500..599 -> serverError(response) else -> throw IllegalStateException("Bummer") public static final int processResponse(@NotNull Response response) { int code = response.code(); int result; if (200 <= code && code <= 299) { result = ok(response); } else if (400 <= code && code <= 499) { result = clientError(response); } else if (500 <= code && code <= 599) { result = serverError(response); } else { throw new IllegalStateException("Bummer"); } }

Slide 137

Slide 137 text

Goodies. Locks inline fun Lock.withLock(action: () -> T): T inline fun ReentrantReadWriteLock.read(action: () -> T): T inline fun ReentrantReadWriteLock.write(action: () -> T): T

Slide 138

Slide 138 text

Goodies. Locks inline fun Lock.withLock(action: () -> T): T inline fun ReentrantReadWriteLock.read(action: () -> T): T inline fun ReentrantReadWriteLock.write(action: () -> T): T val dbLock = ReentrantReadWriteLock() dbLock.write { writeToDb(entity) }

Slide 139

Slide 139 text

inline fun measureNanoTime(block: () -> Unit) : Long inline fun measureTimeMillis(block: () -> Unit) : Long Goodies. System

Slide 140

Slide 140 text

inline fun measureNanoTime(block: () -> Unit) : Long inline fun measureTimeMillis(block: () -> Unit) : Long val saveTime = measureNanoTime { writeToDb(entity) } println("Saving is soo sloow ${saveTime}ns") Goodies. System

Slide 141

Slide 141 text

Goodies. Targeting Java 8 fun Stream.toList(): List fun Stream.asSequence(): Sequence fun Sequence.asStream(): Stream

Slide 142

Slide 142 text

Takeaways ● No big inline method bodies ● Public API in public inline functions ● Reified functions are not present in bytecode ● Eager collection processing functions ● Use Sequence ● “as”/”to” prefix convention ● Ranges optimisations

Slide 143

Slide 143 text

Anko

Slide 144

Slide 144 text

Anko. What I bet you know inline fun Context. startActivity(vararg params: Pair) inline fun Context. intentFor(vararg params: Pair): Intent

Slide 145

Slide 145 text

Anko. What I bet you know inline fun Context. startActivity(vararg params: Pair) inline fun Context. intentFor(vararg params: Pair): Intent fun Context. toast(message: Int) longToast(message: Int)

Slide 146

Slide 146 text

Anko. What I bet you know inline fun Context. startActivity(vararg params: Pair) inline fun Context. intentFor(vararg params: Pair): Intent fun Context. toast(message: Int) longToast(message: Int) val Context. alarmManager: AlarmManager audioManager: AudioManager connectivityManager: ConnectivityManager notificationManager: NotificationManager layoutInflater: LayoutInflater vibrator: Vibrator // ...

Slide 147

Slide 147 text

Anko. What else?

Slide 148

Slide 148 text

Anko. What else? Collections inline fun List. forEachByIndex(f: (T) -> Unit) forEachWithIndex(f: (Int, T) -> Unit) // + Reversed

Slide 149

Slide 149 text

Anko. What else? Collections inline fun List. forEachByIndex(f: (T) -> Unit) forEachWithIndex(f: (Int, T) -> Unit) // + Reversed

Slide 150

Slide 150 text

Anko. What else? Collections inline fun List. forEachByIndex(f: (T) -> Unit) forEachWithIndex(f: (Int, T) -> Unit) // + Reversed inline fun SparseArray. forEach(action: (Int, T) -> Unit) asSequence(): Sequence

Slide 151

Slide 151 text

Anko. What else? ViewGroup Iteration fun ViewGroup. forEachChild(action: (View) -> Unit) forEachChildWithIndex(action: (Int, View) -> Unit) firstChild(predicate: (View) -> Boolean): View

Slide 152

Slide 152 text

Anko. What else? ViewGroup Iteration fun ViewGroup. forEachChild(action: (View) -> Unit) forEachChildWithIndex(action: (Int, View) -> Unit) firstChild(predicate: (View) -> Boolean): View

Slide 153

Slide 153 text

Anko. What else? ViewGroup Iteration fun ViewGroup. forEachChild(action: (View) -> Unit) forEachChildWithIndex(action: (Int, View) -> Unit) firstChild(predicate: (View) -> Boolean): View fun View.childrenRecursiveSequence(): Sequence

Slide 154

Slide 154 text

Anko. What else? Configuration Helpers doFromSdk(Build.VERSION_CODES.M) { window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR } configuration(uiMode = UiMode.CAR, nightMode = true) { schedulePlaySong("System Of A Down - Chop Suey!") }

Slide 155

Slide 155 text

inline fun Activity.find(@IdRes id: Int): T inline fun Activity.findOptional(@IdRes id: Int): T? Anko. What else? ViewUtils

Slide 156

Slide 156 text

inline fun Activity.find(@IdRes id: Int): T inline fun Activity.findOptional(@IdRes id: Int): T? val callBtn = findViewById(R.id.callBtn) as Button Anko. What else? ViewUtils

Slide 157

Slide 157 text

inline fun Activity.find(@IdRes id: Int): T inline fun Activity.findOptional(@IdRes id: Int): T? val callBtn = findViewById(R.id.callBtn) as Button val callBtn = find(R.id.callBtn) Anko. What else? ViewUtils

Slide 158

Slide 158 text

fun bundleOf(vararg params: Pair): Bundle Anko. What else? Bundles

Slide 159

Slide 159 text

fun bundleOf(vararg params: Pair): Bundle fun showMap(location: LatLng, zoomLevel: Int) { val mapFragment = MapFragment().apply { arguments = bundleOf( EXTRA_LOCATION_KEY to location, EXTRA_ZOOM_KEY to zoomLevel ) } showFragment(mapFragment) } Anko. What else? Bundles

Slide 160

Slide 160 text

fun T.withArguments(vararg params: Pair): T fun showMap(location: LatLng, zoomLevel: Int) { val mapFragment = MapFragment().withArguments( EXTRA_LOCATION_KEY to location, EXTRA_ZOOM_KEY to zoomLevel ) showFragment(mapFragment) } Anko. What else? Bundles

Slide 161

Slide 161 text

What was left behind ● Hidden costs of language constructs ○ Exploring Kotlin’s hidden costs  series, https://goo.gl/Gh4uxK ● @Jvm* annotations - Kotlin->Java interop ○ Writing Java-friendly Kotlin code, Mobius https://goo.gl/mXedcb ● @DslMarker ○ Fantastic DSLs and Where to Find Them, https://goo.gl/vcGmmG ● Different Annotation targets ● Reflection ● Coroutines ○ Корутины в Kotlin - Роман Елизаров, https://goo.gl/wUWSpv

Slide 162

Slide 162 text

Q/A Sergey Ryabov | twitter.com/colriot