feel of kotlin (berlin jug 16 apr 2015)

85
The Feel of Kotlin Dmitry Jemerov <[email protected]>

Upload: intelliyole

Post on 17-Jul-2015

94 views

Category:

Software


1 download

TRANSCRIPT

The Feel of KotlinDmitry Jemerov <[email protected]>

What’s Kotlin?

What’s Kotlin?

• Statically typed programming language

What’s Kotlin?

• Statically typed programming language

• Targets JVM, Android and Web

What’s Kotlin?

• Statically typed programming language

• Targets JVM, Android and Web

• In development since mid-2010

Why Kotlin?

• Concise

• Expressive

• Safe

• Develop with Pleasure!

Why Not <other JVM language>?

Why Not <other JVM language>?

• 100% Java interoperability

Why Not <other JVM language>?

• 100% Java interoperability

• 100% Java performance

Why Not <other JVM language>?

• 100% Java interoperability

• 100% Java performance

• Smooth learning curve

Why Not <other JVM language>?

• 100% Java interoperability

• 100% Java performance

• Smooth learning curve

• Maintaining existing investment

Why Not <other JVM language>?

• 100% Java interoperability

• 100% Java performance

• Smooth learning curve

• Maintaining existing investment

• Focus on developer tools

Kotlin at JetBrains

Kotlin at JetBrains• Kotlin itself

Kotlin at JetBrains• Kotlin itself

• Customer portal

Kotlin at JetBrains• Kotlin itself

• Customer portal

• Plugins for IntelliJ IDEA, TeamCity

Kotlin at JetBrains• Kotlin itself

• Customer portal

• Plugins for IntelliJ IDEA, TeamCity

• YouTrack v.next

Kotlin at JetBrains• Kotlin itself

• Customer portal

• Plugins for IntelliJ IDEA, TeamCity

• YouTrack v.next

• Major new product (unannounced)

Hello Worldpackage helloWorldfun main(args: Array<String>) { println("Hello ${args[0]}") }

Hello Worldpackage helloWorldfun main(args: Array<String>) { println("Hello ${args[0]}") }

Hello Worldpackage helloWorldfun main(args: Array<String>) { println("Hello ${args[0]}") }

Hello Worldpackage helloWorldfun main(args: Array<String>) { println("Hello ${args[0]}") }

Classesclass Person(val firstName: String, val lastName: String) { val fullName: String get() = "$firstName $lastName" }

Classesclass Person(val firstName: String, val lastName: String) { val fullName: String get() = "$firstName $lastName" }

Traits and Objectstrait Exprclass Constant(val value: Double) : Exprclass Sum(val op1: Expr, val op2: Expr) : Exprobject NotANumber : Expr

Traits and Objectstrait Exprclass Constant(val value: Double) : Exprclass Sum(val op1: Expr, val op2: Expr) : Exprobject NotANumber : Expr

Traits and Objectstrait Exprclass Constant(val value: Double) : Exprclass Sum(val op1: Expr, val op2: Expr) : Exprobject NotANumber : Expr

Smart Castsfun eval(e: Expr): Double = when(e) { is Constant -> e.value is Sum -> eval(e.op1) + eval(e.op2) NotANumber -> Double.NaN else -> throw IllegalArgumentException()}

Smart Castsfun eval(e: Expr): Double = when(e) { is Constant -> e.value is Sum -> eval(e.op1) + eval(e.op2) NotANumber -> Double.NaN else -> throw IllegalArgumentException()}

Smart Castsfun eval(e: Expr): Double = when(e) { is Constant -> e.value is Sum -> eval(e.op1) + eval(e.op2) NotANumber -> Double.NaN else -> throw IllegalArgumentException()}

Smart Castsfun eval(e: Expr): Double = when(e) { is Constant -> e.value is Sum -> eval(e.op1) + eval(e.op2) NotANumber -> Double.NaN else -> throw IllegalArgumentException()}

Smart Castsfun eval(e: Expr): Double = when(e) { is Constant -> e.value is Sum -> eval(e.op1) + eval(e.op2) NotANumber -> Double.NaN else -> throw IllegalArgumentException()}

Extension Functionsfun Expr.eval(): Double = when(this) { is Constant -> value is Sum -> op1.eval() + op2.eval() NotANumber -> Double.NaN else -> throw IllegalArgumentException()}

Extension Functionsfun Expr.eval(): Double = when(this) { is Constant -> value is Sum -> op1.eval() + op2.eval() NotANumber -> Double.NaN else -> throw IllegalArgumentException()}

Extension Functionsfun Expr.eval(): Double = when(this) { is Constant -> value is Sum -> op1.eval() + op2.eval() NotANumber -> Double.NaN else -> throw IllegalArgumentException()}

Operator Overloadingfun Expr.plus(rhs: Expr) = Sum(this, rhs)val Double.toExpr: Expr get() = Constant(this) fun exprTest() { val expr = 1.0.toExpr + 2.0.toExpr println(eval(expr))}

Operator Overloadingfun Expr.plus(rhs: Expr) = Sum(this, rhs)val Double.toExpr: Expr get() = Constant(this) fun exprTest() { val expr = 1.0.toExpr + 2.0.toExpr println(eval(expr))}

Operator Overloadingfun Expr.plus(rhs: Expr) = Sum(this, rhs)val Double.toExpr: Expr get() = Constant(this) fun exprTest() { val expr = 1.0.toExpr + 2.0.toExpr println(eval(expr))}

Operator Overloadingfun Expr.plus(rhs: Expr) = Sum(this, rhs)val Double.toExpr: Expr get() = Constant(this) fun exprTest() { val expr = 1.0.toExpr + 2.0.toExpr println(eval(expr))}

Operator Overloadingfun Expr.plus(rhs: Expr) = Sum(this, rhs)val Double.toExpr: Expr get() = Constant(this) fun exprTest() { val expr = 1.0.toExpr + 2.0.toExpr println(eval(expr))}

Nullabilityopen class TreeNode(val parent: TreeNode?, val left: TreeNode?, val right: TreeNode?) { fun depth(): Int { val parentDepth = if (parent != null) parent.depth() else 0 return parentDepth + 1 } }

Nullabilityopen class TreeNode(val parent: TreeNode?, val left: TreeNode?, val right: TreeNode?) { fun depth(): Int { val parentDepth = if (parent != null) parent.depth() else 0 return parentDepth + 1 } }

Nullabilityclass TreeNode(val parent: TreeNode?, val left: TreeNode?, val right: TreeNode?) { fun depth(): Int { return (parent?.depth() ?: 0) + 1 } }

Nullabilityclass TreeNode(val parent: TreeNode?, val left: TreeNode?, val right: TreeNode?) { fun depth(): Int { return (parent?.depth() ?: 0) + 1 } }

Elvis Return

fun TreeNode.isBalanced(): Boolean { val l = left?.depth() ?: return false val r = right?.depth() ?: return false return l == r}

Default Parameter Valuesfun List<String>.join(sep: String = ", ") : String { val sb = StringBuilder() for (i in 0..size()-1) { if (i > 0) sb.append(sep) sb.append(this[i]) } return sb.toString()}

Default Parameter Valuesfun List<String>.join(sep: String = ", ") : String { val sb = StringBuilder() for (i in 0..size()-1) { if (i > 0) sb.append(sep) sb.append(this[i]) } return sb.toString()}

Default Parameter Valuesfun List<String>.join(sep: String = ", ") : String { val sb = StringBuilder() for (i in 0..size()-1) { if (i > 0) sb.append(sep) sb.append(this[i]) } return sb.toString()}

Mapsval developers = mapOf( "Kotlin" to "Andrey", "Python" to "Guido") fun report() { for((language, author) in developers) { println("$author made $language") } println("${developers["Kotlin"]} rocks") }

Mapsval developers = mapOf( "Kotlin" to "Andrey", "Python" to "Guido") fun report() { for((language, author) in developers) { println("$author made $language") } println("${developers["Kotlin"]} rocks") }

Mapsval developers = mapOf( "Kotlin" to "Andrey", "Python" to "Guido") fun report() { for((language, author) in developers) { println("$author made $language") } println("${developers["Kotlin"]} rocks") }

Mapsval developers = mapOf( "Kotlin" to "Andrey", "Python" to "Guido") fun report() { for((language, author) in developers) { println("$author made $language") } println("${developers["Kotlin"]} rocks") }

Collections

fun nobleNames(persons: List<Person>) = persons .filter { "von " in it.lastName } .sortBy { it.firstName } .map { "${it.firstName} ${it.lastName}” }

Collections

fun nobleNames(persons: List<Person>) = persons .filter { "von " in it.lastName } .sortBy { it.firstName } .map { "${it.firstName} ${it.lastName}” }

Collections

fun nobleNames(persons: List<Person>) = persons .filter { "von " in it.lastName } .sortBy { it.firstName } .map { "${it.firstName} ${it.lastName}” }

Collections

fun nobleNames(persons: List<Person>) = persons .filter { "von " in it.lastName } .sortBy { it.firstName } .map { "${it.firstName} ${it.lastName}” }

Inline Functionspublic inline fun <T> Iterable<T>.filter( predicate: (T) -> Boolean): List<T> { val destination = ArrayList<T>() for (element in this) { if (predicate(element)) destination.add(element) } return destination}

Inline Functionspublic inline fun <T> Iterable<T>.filter( predicate: (T) -> Boolean): List<T> { val destination = ArrayList<T>() for (element in this) { if (predicate(element)) destination.add(element) } return destination}

Inline Functionspublic inline fun <T> Iterable<T>.filter( predicate: (T) -> Boolean): List<T> { val destination = ArrayList<T>() for (element in this) { if (predicate(element)) destination.add(element) } return destination}

Function References

fun nobles(persons: List<Person>) = persons.filter(::isNoble) fun isNoble(person: Person) = person.lastName.startsWith("von ") || person.lastName.startsWith("zu ")

Member Extensions

class Person(val firstName: String, val lastName: String) { fun isNoble() = lastName.hasNoblePrefix() fun String.hasNoblePrefix() = startsWith("von ") || startsWith("zu ") }

Reified Type Parametersinline fun <reified T> TreeNode.findParentOfType(): T? { var p = parent while (p != null && p !is T) { p = p?.parent } return p as T }

fun findDirectory(node: TreeNode) = node.findParentOfType<DirectoryNode>()

Reified Type Parametersinline fun <reified T> TreeNode.findParentOfType(): T? { var p = parent while (p != null && p !is T) { p = p?.parent } return p as T }

fun findDirectory(node: TreeNode) = node.findParentOfType<DirectoryNode>()

Reified Type Parametersinline fun <reified T> TreeNode.findParentOfType(): T? { var p = parent while (p != null && p !is T) { p = p?.parent } return p as T }

fun findDirectory(node: TreeNode) = node.findParentOfType<DirectoryNode>()

Reified Type Parametersinline fun <reified T> TreeNode.findParentOfType(): T? { var p = parent while (p != null && p !is T) { p = p?.parent } return p as T }

fun findDirectory(node: TreeNode) = node.findParentOfType<DirectoryNode>()

HTML Buildersh1 { +"No Users"} p { +"No users found. Please make sure " a { href = TeamRoute("invitations", team) +"invitation codes" } +" are available to eligible users."}

HTML Buildersh1 { +"No Users"} p { +"No users found. Please make sure " a { href = TeamRoute("invitations", team) +"invitation codes" } +" are available to eligible users."}

HTML Buildersh1 { +"No Users"} p { +"No users found. Please make sure " a { href = TeamRoute("invitations", team) +"invitation codes" } +" are available to eligible users."}

Kotlin Tooling

Kotlin Tooling

• IntelliJ plugin since day 0

Kotlin Tooling

• IntelliJ plugin since day 0

• Eclipse plugin just reached alpha

Kotlin Tooling

• IntelliJ plugin since day 0

• Eclipse plugin just reached alpha

• Ant, Maven, Gradle plugins

Kotlin for Android

Kotlin for Android

• Compiler extension to inject views

Kotlin for Android

• Compiler extension to inject views

• Builder DSL to construct user interfaces

Kotlin for Android

• Compiler extension to inject views

• Builder DSL to construct user interfaces

• Fully compatible with Android Studio

Status of Kotlin

Status of Kotlin

• Compiler and IntelliJ IDEA plugin stable andproduction-ready

Status of Kotlin

• Compiler and IntelliJ IDEA plugin stable andproduction-ready

• Finalizing design of language and standard library

Status of Kotlin

• Compiler and IntelliJ IDEA plugin stable andproduction-ready

• Finalizing design of language and standard library

• Expecting 1.0 release later this year

Summary

Summary

• Kotlin is safe, concise and expressive

Summary

• Kotlin is safe, concise and expressive

• Kotlin can be gradually introduced in any existingJava project

Summary

• Kotlin is safe, concise and expressive

• Kotlin can be gradually introduced in any existingJava project

• Kotlin is stable and ready for production use

Q&A

http://kotlinlang.org/

@intelliyole [email protected]