News from the Kotlin Standard Library Svetlana Isakova October 13, - - PowerPoint PPT Presentation

news from the kotlin standard library svetlana isakova
SMART_READER_LITE
LIVE PREVIEW

News from the Kotlin Standard Library Svetlana Isakova October 13, - - PowerPoint PPT Presentation

Kotlin 1.4 Online Event News from the Kotlin Standard Library Svetlana Isakova October 13, 2020 @sveta_isakova News from the Kotlin standard library New functionality in Kotlin 1.4 Using stdlib in multiplatform projects


slide-1
SLIDE 1

Kotlin 1.4 Online Event @sveta_isakova October 13, 2020

News from the Kotlin Standard Library Svetlana Isakova

slide-2
SLIDE 2

News from the Kotlin standard library

  • New functionality in Kotlin 1.4
  • Using stdlib in multiplatform projects
  • Experimental functionality
slide-3
SLIDE 3

New functionality in Kotlin 1.4

slide-4
SLIDE 4

New functionality in stdlib

  • Making stdlib consistent and meet your expectations
  • New functions: runningFold, runningReduce
  • New types: ArrayDeque
  • New operations for bit manipulation
slide-5
SLIDE 5

Naming conventions: *orNull

"string". toIntOrNull toBigDecimalOrNull collection. firstOrNull lastOrNull elementAtOrNull randomOrNull singleOrNull return null on error: "string". toInt toBigDecimal collection. first last elementAt random single NEW IN throw exception on error:

slide-6
SLIDE 6

max, min

val list = listOf(1, 2, 3) val max: Int? = list.max()

slide-7
SLIDE 7

max, min

val list = listOf(1, 2, 3) val max: Int? = list.max() Replace with maxOrNull

slide-8
SLIDE 8

max, min

val list = listOf(1, 2, 3) val max: Int? = list.maxOrNull() NEW IN

slide-9
SLIDE 9

max, min

  • max/min are deprecated in 1.4
  • maxOrNull/minOrNull should be used instead
  • max/min returning non-null value

will be reintroduced in future versions

slide-10
SLIDE 10

maxBy, minBy

  • maxBy/minBy are deprecated in 1.4
  • maxByOrNull/minByOrNull should be used instead
  • maxBy/minBy returning non-null value will

be reintroduced in future versions

slide-11
SLIDE 11

maxBy vs maxOf

val oldest = people.maxByOrNull { it.age } val maxAge = oldest?/age maxBy returns the element with the largest value maxOf returns the largest value itself val maxAge = people.maxOf { it.age }

slide-12
SLIDE 12

minOf, minOfOrNull

val minAge = people.minOf { it.age } val minAgeOrNull = people.minOfOrNull { it.age } NEW IN

slide-13
SLIDE 13

collection. forEach

  • nEach

filter map flatMap fold reduce

Naming conventions: *Indexed

collection. forEachIndexed

  • nEachIndexed

filterIndexed mapIndexed flatMapIndexed foldIndexed reduceIndexed take an additional parameter, an index, to perform an operation: NEW IN NEW IN perform an operation

  • n each element:
slide-14
SLIDE 14

Naming conventions: *Indexed

collection. forEachIndexed

  • nEachIndexed

filterIndexed mapIndexed flatMapIndexed foldIndexed reduceIndexed take an additional parameter, an index, to perform an operation: perform an operation

  • n each element:

collection. forEach

  • nEach

filter map flatMap fold reduce

slide-15
SLIDE 15

forEach vs onEach

  • rders

.filter { order -? order.client => clientId } .onEachIndexed { index, order -? log("Order by $clientId [$index]: ${order.id}") } .flatMap(Order:;items)

Performs the given action on each element, and returns the collection itself afterwards

  • rders.forEach(:;println)

Performs the given action on each element

slide-16
SLIDE 16

Naming conventions: *IndexedOrNull

collection. reduce reduceIndexed reduceOrNull reduceIndexedOrNull NEW IN NEW IN

slide-17
SLIDE 17

reduceIndexedOrNull

val list = listOf(1, 2, 3) println(list.reduce { a, b -? a + b }) /0 6

Returns null if the collection is empty

val emptyList = emptyList<Int>() println(emptyList.reduceOrNull { a, b -? a + b }) /0 null

slide-18
SLIDE 18

reduceIndexedOrNull

val list = listOf(1, 2, 3) println(list.reduceOrNull { a, b -? a + b }) /0 6

Returns null if the collection is empty

emptyList.reduceIndexedOrNull { index, acc, e -? ../ }

Returns null if the collection is empty Takes an additional parameter, an index, to perform an operation

val emptyList = emptyList<Int>() println(emptyList.reduceOrNull { a, b -? a + b }) /0 null

slide-19
SLIDE 19

New functions: runningReduce

/0 15 /0 [1, 3, 6, 10, 15] (1./5).reduce { sum, elem -? sum + elem } (1./5).runningReduce { sum, elem -? sum + elem }

slide-20
SLIDE 20

New functions: runningReduce

1 2 3 4 5 3 6 10 15 15 1 (1./5).reduce { sum, elem -? sum + elem } (1./5).runningReduce { sum, elem -? sum + elem } 3 6 10 15

slide-21
SLIDE 21

New functions: runningFold (scan)

/0 10 /0 [0, 1, 3, 6, 10] (1./4).runningFold(0) { acc, elem -? acc + elem } (1./4).fold(0) { acc, elem -? acc + elem }

slide-22
SLIDE 22

New functions: runningFold (scan)

(1./4).runningFold(0) { acc, elem -? acc + elem } (1./4).fold(0) { acc, elem -? acc + elem } 1 3 6 10 10 10 1 3 1 2 3 4 6

slide-23
SLIDE 23

New type: ArrayDeque

  • “double-ended queue”
  • provides methods for convenient both-ends access
  • is part of the common library
  • implements MutableList
slide-24
SLIDE 24

Using ArrayDeque

val deque = ArrayDeque(listOf("d", "e", “f"))

f . . . . e d size = 3 head

slide-25
SLIDE 25

Using ArrayDeque

val deque = ArrayDeque(listOf("d", "e", “f")) deque.addFirst("c")

f . . . . e d size = 4 head c

slide-26
SLIDE 26

Using ArrayDeque

val deque = ArrayDeque(listOf("d", "e", “f")) deque.addFirst("c") deque.addFirst("b")

f . . . . e d size = 5 head c b

slide-27
SLIDE 27

Using ArrayDeque

f . . . . e d size = 6 head c b a

val deque = ArrayDeque(listOf("d", "e", “f")) deque.addFirst("c") deque.addFirst("b") deque.addFirst("a")

slide-28
SLIDE 28

New type: ArrayDeque

  • use it whenever you need a Queue

val queue = ArrayDeque<Char>() queue.addLast('a') queue.addLast('b') queue.removeFirst() /0 'a'

slide-29
SLIDE 29

Functions for bit manipulation

val number = "1010000".toInt(radix = 2) 80 2+2=64+16

6 4

slide-30
SLIDE 30

Functions for bit manipulation

val number = "1010000".toInt(radix = 2) number.countOneBits() 1010000 2

slide-31
SLIDE 31

Functions for bit manipulation

val number = "1010000".toInt(radix = 2) number.countOneBits() number.countTrailingZeroBits() 1010000 1010000 4 2

slide-32
SLIDE 32

Functions for bit manipulation

val number = "1010000".toInt(radix = 2) number.countOneBits() number.countTrailingZeroBits() number.takeHighestOneBit().toString(2) 1010000 1010000 1010000 1000000 4 2

slide-33
SLIDE 33

Using the standard library in multiplatform projects

slide-34
SLIDE 34

Different versions for different platforms

common code jvm code js code native code

stdlib-common stdlib-jvm stdlib-js stdlib for Native targets

slide-35
SLIDE 35

Dependency on stdlib by default

  • A dependency on the standard library is added

automatically in each source set

  • With the same version as the Kotlin Gradle plugin
  • For platform-specific source sets,

the platform-specific variant of the library is used

slide-36
SLIDE 36

Extending the common library

  • Trying to make it on par with the JVM stdlib

(which the most used)

  • Adding or moving missing functionality

to the common library

slide-37
SLIDE 37

Extending the common library

  • Extending StringBuilder in the common library
  • Common reflection API is revised
  • Common exception processing API
slide-38
SLIDE 38

Common exception processing API

  • Throwable.stackTraceToString()
  • Throwable.printStackTrace()
  • Throwable.addSuppressed()
slide-39
SLIDE 39

Common @Throws annotation

@kotlin.Throws @kotlin.jvm.Throws @kotlin.native.Throws

  • For interoperability with languages that have

checked exceptions or errors, like Java or Swift

  • Can be used from common code
slide-40
SLIDE 40

Experimental functionality

slide-41
SLIDE 41

Experimental stdlib API

@OptIn(ExperimentalStdlibApi:;class) fun main() { /0 using experimental API }

slide-42
SLIDE 42

Opt-In requirements

  • Allows requiring and giving explicit consent

for using certain elements of APIs

  • Was renamed from @UseExperimental

to cover more use-cases

  • The goal: let early adopters try the new

features as soon as possible

slide-43
SLIDE 43

New API in your library

@RequiresOptIn( level = Level.WARNING, message = "This API can change ⚠" ) annotation class BleedingEdgeAPI @BleedingEdgeAPI class Foo { ../ } @BleedingEdgeAPI fun fetchFoo(): Foo { ../ }

slide-44
SLIDE 44

New API in your library

@RequiresOptIn( level = Level.ERROR, message = "This API can change ⚠" ) annotation class BleedingEdgeAPI @BleedingEdgeAPI class Foo { ../ } @BleedingEdgeAPI fun doSomething(): Foo { ../ }

slide-45
SLIDE 45

Clients using your new API

fun doSomething() { val foo = Foo() } This API can change ⚠

slide-46
SLIDE 46

Clients using your new API

@OptIn(BleedingEdgeAPI:;class) fun doSomething() { val foo = Foo() }

slide-47
SLIDE 47

New experimental stdlib API

  • Collection builders
  • Time measurement API
slide-48
SLIDE 48

Collection builders

  • buildList
  • buildSet
  • buildMap
slide-49
SLIDE 49

Similar to buildString

val str: String = buildString { this.appendLine("Chars:") for (ch in 'a'./'i') { append(ch) } } println(str) /0 Chars: /0 abcdefghi

slide-50
SLIDE 50

Collection builders

val needsZero = true val initial = listOf(2, 6, 41) val ints = buildList { if (needsZero) { add(0) } initial.mapTo(this) { it + 1 } } println(ints) /0 [0, 3, 7, 42]

slide-51
SLIDE 51

Collection builders

val needsZero = true val initial = listOf(2, 6, 41) val ints = buildList { if (needsZero) { add(0) } initial.mapTo(this) { it + 1 } } println(ints) /0 [0, 3, 7, 42]

this: MutableList

slide-52
SLIDE 52

Collection builders

val needsZero = true val initial = listOf(2, 6, 41) val ints = buildList { if (needsZero) { add(0) } initial.mapTo(this) { it + 1 } } println(ints) /0 [0, 3, 7, 42]

this: MutableList

List

slide-53
SLIDE 53

Measuring time

import kotlin.time.* val duration: Duration = measureTime { Thread.sleep(1050) /0 action } duration.inSeconds /0 1.056486657 duration.inMilliseconds /0 1056.486657

slide-54
SLIDE 54

Measuring time

import kotlin.time.* val clock = TimeSource.Monotonic val mark = clock.markNow() Thread.sleep(200) println(mark.elapsedNow()) /0 e.g. 206ms action

slide-55
SLIDE 55

Measuring time

import kotlin.time.* val clock = TimeSource.Monotonic val mark = clock.markNow() Thread.sleep(200) println(mark.elapsedNow()) /0 e.g. 206ms might be inside the first function might be inside the second function

slide-56
SLIDE 56

Measuring time & getting the resulting value

import kotlin.time.* val (value, duration) = measureTimedValue { Thread.sleep(100) 42 } println(value) /0 42 println(duration) /0 e.g. 103ms

slide-57
SLIDE 57

Dates and Time

  • github.com/Kotlin/kotlinx-datetime
  • ‘Introducing DateTime’ talk
slide-58
SLIDE 58

Summary

slide-59
SLIDE 59

What we’ve discussed

New stable functionality Experimental functionality stdlib in multiplatform projects @OptIn stdlib dependency by default extending the common library bit manipulation consistent stdlib

runningReduce runningFold ArrayDeque

collection builders time measurement

slide-60
SLIDE 60

What’s New in 1.4 documentation page

slide-61
SLIDE 61

What’s New in 1.4 documentation page

slide-62
SLIDE 62

@sveta_isakova

Thanks! Have a nice Kotlin!