2017: kotlin - now more than ever

48
2017: KOTLIN - NOW MORE THAN EVER! KAI KOENIG (@AGENTK)

Upload: kai-koenig

Post on 15-Apr-2017

58 views

Category:

Software


1 download

TRANSCRIPT

Page 1: 2017: Kotlin - now more than ever

2017: KOTLIN - NOW MORE THAN EVER! KAI KOENIG (@AGENTK)

Page 2: 2017: Kotlin - now more than ever

AGENDA

AGENDA

▸ What is Kotlin?

▸ Idioms and language concepts

▸ The 1.1 release

▸ Where does that leave Android

▸ Outside the box

▸ Final thoughts

Page 3: 2017: Kotlin - now more than ever

WHAT IS KOTLIN?

Page 4: 2017: Kotlin - now more than ever

WHAT IS KOTLIN?

SOME KOTLIN FUNDAMENTALS

▸ Statically typed programming language for JVM and Android

▸ Started as internal language “Project Kotlin” at Jetbrains in July 2010

▸ Kotlin 1.0 since Feb 2016

▸ Now: Open-Source, Apache License

▸ Named after an island in the Gulf of Finland

Page 5: 2017: Kotlin - now more than ever

HISTORY OF KOTLIN (I)

▸ Jetbrains wanted a more efficient JVM language when building products

▸ Looked at Scala, Groovy, etc, but came up with their own language spec

▸ Shown first at the JVM Language Summit in 2011

▸ Got some traction in Android-land in 2014

▸ modern language features (lambdas, HOF etc) but Java 6-bytecode

▸ Low methods count (~7000)

▸ Strong focus on concision and an efficient, bloat-free language

WHAT IS KOTLIN?

Page 6: 2017: Kotlin - now more than ever

HISTORY OF KOTLIN (II)

▸ Since 1.0 release: multiple maintenance releases up to 1.0.7

▸ 1.1 was released in Feb 2017, now at 1.1.1

▸ Kotlin/JS is a first-class deployment/compilation target now

▸ Coroutines

▸ Some stdlib cleanup

▸ Strong community, lots of interesting frameworks, awesome support from Jetbrains

WHAT IS KOTLIN?

Page 7: 2017: Kotlin - now more than ever

HOW DOES A SIMPLE CONVERSION LOOK LIKE?public String listConvert(Collection<Integer> collection) { StringBuilder sb = new StringBuilder(); sb.append("{"); Iterator<Integer> iterator = collection.iterator(); while (iterator.hasNext()) { Integer element = iterator.next(); sb.append(element); if (iterator.hasNext()) { sb.append(", "); } } sb.append("}"); return sb.toString(); }

fun listConvert(collection: Collection<Int>): String { val sb = StringBuilder() sb.append("{") val iterator = collection.iterator() while (iterator.hasNext()) { val element = iterator.next() sb.append(element) if (iterator.hasNext()) { sb.append(", ") } } sb.append("}") return sb.toString() }

fun listConvertKt(collection: Collection<Int>): String { return collection.joinToString(prefix = "{",postfix = "}") }

WHAT IS KOTLIN?

Page 8: 2017: Kotlin - now more than ever

IDIOMS & LANGUAGE PATTERNS

https://www.flickr.com/photos/geraldford/6976818221/

Page 9: 2017: Kotlin - now more than ever

IDIOMS & LANGUAGE PATTERNS

IDIOM AND LANGUAGE OVERVIEW

▸ Immutability

▸ String templates

▸ Null safety

▸ Properties and Fields

▸ Data classes

▸ Extension functions

▸ Syntactic sugar

▸ Type inference

▸ Lambdas

▸ Collection API

▸ Type-safe builders

▸ Java-Kotlin-Interop

Page 10: 2017: Kotlin - now more than ever

IDIOMS & LANGUAGE PATTERNS

IMMUTABILITY

▸ Support for mutable and immutable variables, properties and fields

▸ Keywords var and val

▸ val - immutable (recommended)

▸ var - mutable

▸ Similar concept applies for class properties

val a: Int = 1 val b = 1

val c: Int c = 1

val x = 23

// fails x += 1

Page 11: 2017: Kotlin - now more than ever

STRING TEMPLATES

▸ Kotlin Strings can contain template expressions

▸ String templates start with a $ character and

▸ can contain simple references such as $s, as well as

▸ complex expressions in curly braces: ${s.length}

val s = "abc" val str = "$s.length is ${s.length}"

Output:

abc.length is 3

IDIOMS & LANGUAGE PATTERNS

Page 12: 2017: Kotlin - now more than ever

NULL SAFETY

▸ An explicit way to deal with NPEs

▸ Nullable types vs non-nullable types:

▸ String: no nullable

▸ String?: nullable

▸ Handle manually

▸ Use Safe Call operator ?.

▸ !! operator to allow/trigger a NPE

// Won't compile var lastName: String = null

// Will compile var lastNameNullable: String? = null

// Will also not compile println(lastNameNullable.length)

// Option 1 (-1) println(if (lastNameNullable != null) lastNameNullable.length else -1)

// Option 2 (null) println(lastNameNullable?.length)

// Option 3 (NPE) println(lastNameNullable!!.length)

IDIOMS & LANGUAGE PATTERNS

Page 13: 2017: Kotlin - now more than ever

PROPERTIES AND FIELDS

▸ Kotlin classes have mutable or immutable properties

▸ Default getter/setters for properties, can be customised

▸ An automated backing field can be provided by the compiler (if required)

▸ Alternative: use an explicit backing property

var counter = 0 set(value) { if (value >= 0) field = value }

public class Address { public var name: String = ... public var street: String = ... public var city: String = ... public var state: String? = ... public var zip: String = ... }

IDIOMS & LANGUAGE PATTERNS

Page 14: 2017: Kotlin - now more than ever

DATA CLASSES

▸ The POJOs/Beans of other languages

▸ Data classes implicitly create:

▸ getters/setters - recommend to use val as often as possible.

▸ useful implementations for equals(), hashCode(), toString(), copy()

▸ copy() has default parameters and can be used to alter a copy

data class ChromeEncryptedPayload( val encryptedPayload: String, val encryptionHeader: String, val cryptoKeyHeader: String)

val pl = ChromeEncryptedPayload( encryptedPayload = "...", encryptionHeader = "...", cryptoKeyHeader = "...")

val anotherPl = pl.copy( encryptedPayload = "...")

IDIOMS & LANGUAGE PATTERNS

Page 15: 2017: Kotlin - now more than ever

SYNTACTIC SUGAR

▸ When-statement

▸ Ranges / Loops

▸ Destructuring

▸ Default and named arguments

IDIOMS & LANGUAGE PATTERNS

fun whatIs(x: Any) { when (x) { is Int -> println(x + 42) is String -> println(x.length) is IntArray -> println(x.sum()) } }

whatIs(4) // 46 whatIs("4") // 1 whatIs(intArrayOf(1,2,3,4,5)) // 15

if (i in 1..10) { println(i) }

val (name, age) = person fun read(b: Array<Byte>, off: Int = 0, len: Int = b.size()) { … }

Page 16: 2017: Kotlin - now more than ever

EXTENSION FUNCTIONS

▸ Allow adding new functionality to a class without inheritance or decorators

▸ Kotlin has extension functions as well as extension properties

▸ Resolved statically, don’t actually modify the class

fun Int.sum(otherInt: Int): Int = this + otherInt

3.sum(7)

fun Activity.toast(message: CharSequence, duration: Int = TOAST.LENGTH_SHORT) { Toast.makeText(this, message, duration).show() }

// In onCreate of an Activity override fun onCreate(...) { ... toast("Hi there") ... }

IDIOMS & LANGUAGE PATTERNS

Page 17: 2017: Kotlin - now more than ever

LAMBDAS

▸ Anonymous function or “function literal”

▸ Closely related to the ideas of Higher-Order-Functions

val sum = { x: Int, y: Int -> x + y }

val sum: (Int, Int) -> Int = { x, y -> x + y }

private fun convertPetListToDomain(list: List<Pet>): List<PetDomain> { return list.map { convertPetItemToDomain(it) } }

private fun convertPetItemToDomain(pet: Pet): PetDomain { return PetDomain(pet.age,pet.size,pet.id,pet.name,pet.sex,pet.breed) }

IDIOMS & LANGUAGE PATTERNS

Page 18: 2017: Kotlin - now more than ever

TYPE-SAFE BUILDERS (I)

▸ Builders are a very popular approach in Groovy to define data in a declarative way

▸ Often used for:

▸ generating XML or JSON

▸ UI layout (Swing components) etc

▸ In Kotlin, builders even can be type-checked

JsonBuilder builder = new JsonBuilder()

builder.records { car { name 'HSV Maloo' make 'Holden' year 2006 country 'Australia' } }

String json = JsonOutput.prettyPrint (builder.toString())

IDIOMS & LANGUAGE PATTERNS

Page 19: 2017: Kotlin - now more than ever

TYPE-SAFE BUILDERS (II)

▸ html() is a function with a lambda as an argument (init)

▸ init’s type is a function type with receiver, this allows you to:

▸ pass receiver (of type HTML) to function

▸ call members of instance inside the function

fun result(args: Array<String>) = html { head { title {”HTML in Kotlin"} } body { ... } }

fun html(init: HTML.() -> Unit): HTML { val html = HTML() html.init() return html }

IDIOMS & LANGUAGE PATTERNS

Page 20: 2017: Kotlin - now more than ever

TYPE-SAFE BUILDERS (III)

▸ Html class has functions to build the head and the body elements of the DSL.

▸ Not shown: classes further down in the hierachy:

▸ Head, Body etc.

▸ Complete HTML builder example at: http://goo.gl/TndcC9

class Html { ...

fun head(headBuilder: Head.() -> Unit) { head = Head() head?.headBuilder() }

fun body(bodyBuilder: Body.() -> Unit) { body = Body() body?.bodyBuilder() } }

IDIOMS & LANGUAGE PATTERNS

Page 21: 2017: Kotlin - now more than ever

THE 1.1 RELEASE

Page 22: 2017: Kotlin - now more than ever
Page 23: 2017: Kotlin - now more than ever

THE 1.1 RELEASE

OVERVIEW (I)

▸ JavaScript target is not experimental anymore (browser & NodeJS)

▸ Full Kotlin language support

▸ Large part of the stdlib is supported

▸ Coroutines (JVM, experimental)

▸ Lightweight concurrency mechanism

▸ Alternative to threads

▸ Tooling improvements

Page 24: 2017: Kotlin - now more than ever

THE 1.1 RELEASE

OVERVIEW (II)

▸ Language features

▸ Type aliases

▸ Bound callable references

▸ More powerful data classes

▸ Destructuring in lambdas

▸ Property syntax

▸ Underscore-parameters for unused variables in lambdas

Page 25: 2017: Kotlin - now more than ever

THE 1.1 RELEASE

COROUTINES (I)

▸ Asynchronous programming is becoming increasingly important

▸ Problem: need to avoid blocking introduces a lot of complexity

▸ Kotlin’s approach: Suspending functions

▸ Function/lambda that can be suspended and resumed

▸ Ideas similar to cooperative multi-tasking

▸ Minimal integration into the core language and stdlib, most of functionality provided by libraries

Page 26: 2017: Kotlin - now more than ever

THE 1.1 RELEASE

COROUTINES (II)

▸ Using coroutines requires explicit import of the Kotlin coroutines libraries

▸ Suspending function can use other suspending functions like delay()

▸ join() waits for the background job on doWorld() to complete.

▸ Light-weight, can act like daemon threads

fun main(args: Array<String>) = runBlocking<Unit> { val job = launch(CommonPool) { doWorld() } println("Hello,") job.join() }

// this is a suspending function suspend fun doWorld() { delay(1000L) println("World!") }

Page 27: 2017: Kotlin - now more than ever

THE 1.1 RELEASE

TOOLING

▸ General approach: avoid tooling to be bound to language releases

▸ But: there’s some new stuff in 1.1:

▸ Updates for all major IDE plugins

▸ Incremental compilation is now a first-class citizen

▸ Linting for Kotlin in Android Studio projects was improved

Page 28: 2017: Kotlin - now more than ever

TYPE ALIASES

▸ Allow to define alternative names for types

▸ Often used with generic types

▸ Different from import aliases

typealias OscarWinners = Map<String, String>

fun countLaLaLand(oscarWinners: OscarWinners) = oscarWinners.count { it.value.contains("La La Land") }

fun checkLaLaLandIsTheBestMovie (oscarWinners: Map<String, String>) = oscarWinners["Best picture"] == "La La Land"

import domain.PetModel as domainPets

THE 1.1 RELEASE

Page 29: 2017: Kotlin - now more than ever

CLASSES

▸ Kotlin 1.1 removes restrictions around data classes and sealed classes

▸ Sealed: don’t need subclassed nested into them anymore

▸ Data: can now extend other classes

THE 1.1 RELEASE

sealed class Expr { class Const(val number: Double) : Expr() class Sum(val e1: Expr, val e2: Expr) : Expr() object NotANumber : Expr() }

fun eval(expr: Expr): Double = when(expr) { is Expr.Const -> expr.number is Expr.Sum -> eval(expr.e1) + eval(expr.e2) Expr.NotANumber -> Double.NaN }

sealed class Expr data class Const(val number: Double) : Expr() data class Sum(val e1: Expr, val e2: Expr) : Expr() object NotANumber : Expr()

fun eval(expr: Expr): Double = when (expr) { is Const -> expr.number is Sum -> eval(expr.e1) + eval(expr.e2) NotANumber -> Double.NaN }

Page 30: 2017: Kotlin - now more than ever

DESTRUCTURING LAMBDAS

▸ Easier unpacking arguments passed to a lambda

THE 1.1 RELEASE

val map = mapOf(1 to "one", 2 to "two")

// before println(map.mapValues { entry -> val (key, value) = entry "$key -> $value!" })

// now println(map.mapValues { (key, value) -> "$key -> $value!" })

Page 31: 2017: Kotlin - now more than ever

COMPATIBILITY

▸ Kotlin 1.1 is backwards compatible to 1.0 on the language and stdlib level

▸ Code that compiled and ran in 1.0 will compile and run in 1.1

▸ More on compat: http://kotlinlang.org/docs/reference/compatibility.html

THE 1.1 RELEASE

Page 32: 2017: Kotlin - now more than ever

WHERE DOES THAT LEAVE ANDROID?

Page 33: 2017: Kotlin - now more than ever

WHERE DOES THAT LEAVE ANDROID?

IT’S STILL JAVA 6

▸ All the new features still work on Java 6

▸ Can be used and deployed to pretty much any current Android device/version

Page 34: 2017: Kotlin - now more than ever

WHERE DOES THAT LEAVE ANDROID?

COROUTINES

▸ At first glance they look like a JVM- or server-side-only feature

▸ However, there are at least 3 libraries around to make coroutines useful in Android:

▸ Anko (support for coroutines since 0.10 beta)

▸ kotlinx-coroutines-android (support for UI operations)

▸ AsyncAwait

Page 35: 2017: Kotlin - now more than ever

WHERE DOES THAT LEAVE ANDROID?

COROUTINES IN ANKO

▸ Add anko-coroutines dependency

▸ Earlier versions of Anko already had support for async handling

▸ New:

▸ Coroutines in listeners

▸ asReference()

▸ bg()

fun getData(): Data { ... } fun showData(data: Data) { ... }

async(UI) { val data: Deferred<Data> = bg { // Runs on the background getData() }

// This code is executed on the UI thread showData(data.await()) }

Page 36: 2017: Kotlin - now more than ever

WHERE DOES THAT LEAVE ANDROID?

COROUTINES WITH KOTLINX-COROUTINES-ANDROID

▸ Centred around launch(UI) metaphor

▸ Launching coroutines in UI context:

▸ allows updating the UI from inside the coroutine and

▸ allows invoking suspending functions at the same time

▸ no frozen UI during delay()

▸ cancel() on coroutine in UI context allows stopping it

▸ Similar libraries exist for JavaFX and Swing

Page 37: 2017: Kotlin - now more than ever

WHERE DOES THAT LEAVE ANDROID?

COROUTINES WITH KOTLINX-COROUTINES-ANDROID

fun setup(hello: TextView, fab: FloatingActionButton) { val job = launch(UI) { for (i in 10 downTo 1) { hello.text = "Countdown $i ..." delay(500) } hello.text = "Done!" } fab.setOnClickListener = { job.cancel() } }

Page 38: 2017: Kotlin - now more than ever

WHERE DOES THAT LEAVE ANDROID?

COROUTINES WITH ASYNCAWAIT

▸ Async/await approach

▸ Very rich library on top of Kotlin’s coroutine core:

▸ awaitWithProgress

▸ try/catch/onError/finally

▸ Plugins for Retrofit and rxJava

async { val result = await { //Long running code } // Use result }

async { val repos = await { github.getRepos() } showList(repos) repos.forEach { repo -> val stats = await { github.getStats (repo.name) } showStats(repo, stats) } }

Page 39: 2017: Kotlin - now more than ever

class AnimalListAdapter constructor (val items: PetList, val listener: ItemClickListener : RecyclerView.Adapter<AnimalListAdapter.ViewHolder>() {

... class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { fun bind(item: Item, listener: ItemClickListener { itemView.setOnClickListener(listener) } }

}

typealias ItemClickListener = (View) -> (Unit)

WHERE DOES THAT LEAVE ANDROID?

TYPE ALIASES

▸ RecyclerView and adapter classes: Replace repeating types with a “click listener” aliasclass AnimalListAdapter constructor (val items: PetList, val listener: (View) -> Unit) : RecyclerView.Adapter<AnimalListAdapter.ViewHolder>() {

... class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { fun bind(item: Item, listener: (View) -> Unit) { itemView.setOnClickListener(listener) } }

}

Page 40: 2017: Kotlin - now more than ever

WHERE DOES THAT LEAVE ANDROID?

TOOLING

▸ Since 1.1beta2: Support for the Jack toolchain (ironic, given that that’s all gonna change again soon)

▸ Some new AS/IntelliJ intentions:

▸ Generating View constructors

▸ Merging if-statements and more

Page 41: 2017: Kotlin - now more than ever

OUTSIDE THE BOX

https://www.flickr.com/photos/sillygwailo/5990089210/

Page 42: 2017: Kotlin - now more than ever

OUTSIDE THE BOX

WHAT ELSE CAN KOTLIN DO FOR YOU?

▸ Use it in Gradle instead of Groovy

▸ Use it as your main script language in TeamCity

▸ Use it with other JVM languages via JSR-223 (javax.script)

Page 43: 2017: Kotlin - now more than ever

OUTSIDE THE BOX

KOTLIN/NATIVE

▸ Brand new preview: Kotlin/Native

▸ Idea: compiling to machine code

▸ Preview targets: OS X 10.10, Ubuntu, iOS, RaspPi

▸ Goal: Ubiquitous language allowing you to write anything from front end code down to machine-code-level back end services

▸ More: https://blog.jetbrains.com/kotlin/2017/04/kotlinnative-tech-preview-kotlin-without-a-vm/

Page 44: 2017: Kotlin - now more than ever

OUTSIDE THE BOX

COMMUNITY

▸ Slack team with ~6000 people

▸ Jetbrains user group/community program

▸ Multiple books and online courses

▸ Jetbrains KEEP process is open for everyone

▸ 4-5x increase in Kotlin LOC in github over the last year

▸ Lots of interesting frameworks being developed

Page 45: 2017: Kotlin - now more than ever

FINAL THOUGHTS

https://www.flickr.com/photos/brickset/16099265973/

Page 46: 2017: Kotlin - now more than ever

FINAL THOUGHTS

MATURITY AND FUTURE

▸ Kotlin 1.0 was a big step for the language, Kotlin 1.1 added very useful new features

▸ Very mature for a 1.x release (but 6+ years in the making), full of great concepts and idioms, getting better with every release

▸ Tool support is A+

▸ KEEP (Kotlin Evolution and Enhancement Process) helps to steer the language’s future

Page 47: 2017: Kotlin - now more than ever

FINAL THOUGHTS

RESOURCES

▸ Kotlin: http://kotlinlang.org

▸ Anko: https://github.com/Kotlin/anko

▸ kotlinx-coroutines-android:

▸ https://github.com/Kotlin/kotlinx.coroutines/tree/master/ui/kotlinx-coroutines-android

▸ https://github.com/Kotlin/kotlinx.coroutines/blob/master/ui/coroutines-guide-ui.md

▸ AsyncAwait: https://github.com/metalabdesign/AsyncAwait

▸ KEEP: https://github.com/Kotlin/KEEP

Page 48: 2017: Kotlin - now more than ever

FINAL THOUGHTS

GET IN TOUCH

Kai Koenig

Email/iMessage: [email protected]

Work: http://www.ventego-creative.co.nz

Twitter: @AgentK

Telegram: @kaikoenig

Slideshare: /agentk