Thanks to our sponsors!

Thank you.

Meet Me:

Dan Lindeman

Software Engineer @ Spantree

(Email: dan@spantree.net)

Master's Student @ GVSU

Meet Kotlin

package demo 
 
fun main(args: Array<String>) { 
  println("Hello, World!") 
}

The Promise

Brief History of Kotlin

Targets

JVM

JavaScript

Native

Who is    otlin for?

  • People who like
    • Pragmatism
    • Typing less
    • Clean interoperability
    • Never getting NullPointerExceptions
  • People who have to
    • Compile to Java 6

My journey to Kotlin

The call to action

Alternatives

  • Jython
    •  (see jRuby)
  • Scala
    • ​Too far "out there"
  • Groovy
    • "The world moved on"
  • Ceylon
    • "Does anyone use this?"

So?

  • Spiked a new project
  • No (coding) hiccups
    • Ant + Kotlin
  • When in doubt, write Java
    • Unidiomatic

Fig 1. A real concern of mine

Most People

  • testsAreAGoodStart.kt
  • smallUtilConvertedTo.kt

 

  • FP shallow end
  • Low risk
  • Fun!

Fig. 2 Ship of Theseus

(see also, your codebase)

Android

  • Google IO
  • No plans to drop JRE 6
  • Android Studio
  • Boilerplate reduction*
view.setOnClickListener(new View.OnClickListener() {
     @Override
     public void onClick(View v) {
         // do whatever you want
}});
view.setOnClickListener { 
    // do whatever you want 
}

*fun fact; There used to be

another column here, but I couldn't fit an Android verbosity example without moving it to another slide.

Unidiomatic Basics

// Constructor in the signature
class Person(age: Int, name: String) {
    // members var for mutable, val for immutable
    var age: Int = age
    val name = name

    fun sayHello() {
        println("Hi, I am $name, and I am $age years old")
    }

    fun countEvensToTen() {
        for (x in 1..10) {
            if (x%2 == 0) {
                println(x)
            } else {
                println("nope")                
            }
        }
    }
    
    fun gimmeFive(): Int { // return type after colon
        return 5
    }

    fun gimmeSomeMore(amount: Int, howMuchMore: Int): Int {
        if (howMuchMore < 1) {
            return amount + 1
        } else {
            return amount + howMuchMore
        }
    }
}

Idiomatic Basics

class Person(var age: Int, val name: String) {
    
    fun sayHello() {
        println("Hi, I am $name, and I am $age years old")
    }

    fun countEvensToTen() {
        (1..10).forEach {
            when {
                (it % 2 == 0) -> println(it)
                else -> println("nope")
            }
        }
    }
    
    fun gimmeFive() =  5

    fun gimmeSomeMore(amount: Int, howMuchMore: Int = 1): Int {
        return amount + howMuchMore
    }
}

fun hello() {

} 

Cool Features!

REPL

Null Safety

Elvis Operator

Extension Functions

Data Classes

Lambdas

Object Classes

Companion Objects

Sealed Classes

Coroutines

Null Safety!

var a: String = "abc"
a = null // compilation error

// To allow nulls, we can declare a variable as nullable string,
// written String?

var b: String? = "abc"
b = null // ok

// Now, if you call a method or access a property on a,
// it’s guaranteed not to cause an NPE, so you can safely say

val l = a.length

// But if you want to access the same property on b,
// that would not be safe, and the compiler reports an error:

val l = b.length // error: variable 'b' can be null

Null Safety (cont'd)

// Safe Calls:

val b: String? = "something"
b?.length
// 9

x = "path/to/file"
var y: List<String> = listOf()

if (x !=  null) {
    y = x.split("/") // notice the lack of a check here!
}

bob?.department?.head?.name
// Useful for chaining
// Returns null if any of the properties in it is null


// Heads up you CAN ignore null safety..
// I'm not going to show you how...
val l = b?.length ?: -1

// If the expression to the left of ?: is not null,
// the elvis operator returns it, 
// otherwise it returns the expression to the right. 
// Note that the right-hand side expression
// is evaluated only if the left-hand side is null.



// This can be very handy, for example, for checking function arguments:

fun foo(node: Node): String? {
    val parent = node.getParent() ?: return null
    val name = node.getName() ?: throw IllegalArgumentException("name expected")
    // ...
}

// Note
fun foo() throws Exception {
    // Not actually possible!!!
}

Elvis Operator

?:

?:

Clean Interop?

.java from .kt

public class Customer {

    private String name;

    public Customer(String s){
        name = s;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
val customer = Customer("Phase")

println(customer.name)

.kt from .java

package demo;


public class plainOldJavaPerson {
    
    ...
    
    public void doStuffFromKotlinFunctions() {
        FunctionalStuffKt.activities();
    }

    public void doStuffFromKotlinClass() {
        Cool c = new Cool(3, "red");
    }

    ...
}
package demo

fun activities() {
    // things
}
package demo

class Cool(val id: Int, val color: String){

    fun reportInfo(): String {
        return "$id, $color"
    }
}

Interop

Side-by-Side!*

*Gradle likes them separate

More Interop

Note: This may kill the git history

REPL

On POJOs

public class User {

    public String name;
    private int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
} // Line 22

Data Classes

data class User(val name: String, var age: Int)
// Kotlin also provides toString(), equals(), hashCode(), and copy()
// val comes with getter (immutable)
// var comes with getter and setter (mutable)

// Copy
// not a deep copy
val jack = User(name = "Jack", age = 1)
val olderJack = jack.copy(age = 2)

// Extracting fields from the class
val jane = User("Jane", 35) 
val (name, age) = jane
println("${jane.name}, ${jane.age} years of age") // prints "Jane, 35 years of age"

// Accessing attributes (also done language-wide)
>>> jane.name 
Jane
>>> jane.age = 36
>>> jane
User(name=Jane, age=36)

>>> jane.name = "Jenny"
java.lang.IllegalAccessError: tried to access field Line3$User.name from class Line7

// As of 1.1 can now extend Sealed Classes. Neat!

Sealed Classes

Extension Functions!

// To declare an extension function, we need to prefix its name
// with a receiver type, i.e. the type being extended. 
// The following adds a swap function to MutableList<T>:

fun <T> MutableList<T>.swap(index1: Int, index2: Int) {
    val tmp = this[index1] // 'this' corresponds to the list
    this[index1] = this[index2 + 1]
    this[index2] = tmp
}

>>> val l = mutableListOf(1, 2, 3)
>>> l
[1, 2, 3]
>>> l.swap(0, 2)
>>> l
[3, 2, 1]

>>> val r = mutableListOf("a", "b", "c")
>>> r.swap(1,2)
>>> r
[a, c, b]

// Extension functions are resolved statically.
// Extensions do not actually modify classes they extend. 
// By defining an extension, you do not insert new members into a class,
// but merely make new functions callable 
// with the dot-notation on instances of this class.

Lambdas

// The full syntactic form of lambda expressions, i.e. literals of function types

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

// A lambda expression is always surrounded by curly braces.
// Parameter declarations in the full syntactic form go inside parentheses 
// and have optional type annotations, 
// the body goes after an -> sign. 

// If we leave all the optional annotations out, what’s left looks like this:

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

// It’s very common that a lambda expression has only one parameter. 
// If Kotlin can figure the signature out itself, 
// it allows us not to declare the only parameter, 
// and will implicitly declare it for us under the name it:

ints.filter { it > 0 } 

Functional Features

    val names = listOf( "Cedric", "Marija", "Jonathan",
                        "Kevin", "Liz", "Richard", "Roberto",
                        "Sebastian", "Justin", "Andy", "Dan")

    val loudNames = names.map { it.toUpperCase() }
    // [CEDRIC, MARIJA, JONATHAN, KEVIN, 
    //  LIZ, RICHARD, ROBERTO, SEBASTIAN, JUSTIN, ANDY, DAN]

    val shortNames = names.filter { it.length < 5 }
    // [Liz, Andy, Dan]

    val groupedNames = names.groupBy { it.first() }
    // {C=[Cedric], M=[Marija], J=[Jonathan, Justin], 
    //  K=[Kevin], L=[Liz], R=[Richard, Roberto], 
    //  S=[Sebastian], A=[Andy], D=[Dan]}

    val letterCount = names.map { it.length }.reduce { a, b -> a + b}
    // 64

Other neat things

  • Coroutines
  • Higher Order Functions
  • Kotlin Uncovered
    • https://academy.realm.io/posts/360-andev-2017-victoria-gonda-kotlin-uncovered/?
  • Exception Handling
    • https://spantree.net/blog/2017/09/15/kotlin-exception-handling-with-kategory.html

(worthy of their own talk)

Tooling

  • Gradle/Maven/Ant
  • IDEs
    • IntelliJ / Android Studio
    • Eclipse Luna
    • Syntax highlighting for 'most editors'
  • Static Analysis 

Nice Libraries

  • Fuel
  • TornadoFX (think JavaFX)
  • Spek (think rspec)
  • Kategory (think cats)
  • requery
  • Spring
  • Any Java library you like

Community

  • Kotlin Slack (very active)
    • Many library maintainers use it
      • Fuel, Kategory
      • Andrey Breslav
  • Talking Kotlin podcast
  • KotlinConf (Nov 2-3)
  • Kotlin Weekly is great!
  • Kotlin User Group support is great!
  • Kotlin Subreddit isn't great...
  • IntelliJ blog frequently updated
  • Kotlin in Action
    • Buy it! It's amazing.

Warts

  • Youth of community
  • Reflection can be wonky
  • JavaScript Story

Future

  • Roadmap for 1.2
    • Improvements/Tooling
  • KEEP Kotlin Evolution and Enhancement Process
    • Similar to Python's PEP

Electric Sheep

Questions?

Sources:

  • https://realm.io/news/droidcon-michael-pardo-kotlin/
  • https://kotlinlang.org/docs/
  • https://blog.jetbrains.com/kotlin/category/releases/
  • https://techbeacon.com/why-you-should-use-kotlin-android-development
  • https://kotlinlang.org/docs/reference/idioms.html
  • Kevin Greene, Roberto Guerra, Victoria Gonda, Mike Langdon, Corbin Phelps, Nikko Stewart

"Not a deep copy"

>>> data class C (val l: MutableList<Int>)
>>> val c = C(mutableListOf(1,2))
>>> val cc = c.copy()
>>> cc.l.add(10)
true
>>> cc.l
[1, 2, 10]
>>> c.l
[1, 2, 10]
>>>

Meet Kotlin

By dlindema

Meet Kotlin

An introduction to the Kotlin Programming language. And some assorted thoughts on why you should consider the language.

  • 1,075