feel of kotlin (berlin jug 16 apr 2015)
TRANSCRIPT
What’s Kotlin?
• Statically typed programming language
• Targets JVM, Android and Web
• In development since mid-2010
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 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)
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
• IntelliJ plugin since day 0
• Eclipse plugin just reached alpha
• Ant, Maven, Gradle plugins
Kotlin for Android
• Compiler extension to inject views
• Builder DSL to construct user interfaces
• Fully compatible with Android Studio
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
• 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