the kotlin programming language, svetlana isakova
DESCRIPTION
Talk given by Svetlana Isakova at scaladev'12 (scaladev.ru)TRANSCRIPT
The Kotlin Programming Language
Svetlana Isakova
2
What? Who? Why?
A modern language Statically typed Object-oriented General-purpose
Compiler
JVM byte code JavaScript (not GWT)
3
What? Who? Why?
A modern language Statically typed Object-oriented General-purpose
Developed by JetBrains
Open source Intended for industrial use
4
Dynamic vs static typing
Dynamically typed languages Easier to learn Easier to write small programs
Statically typed languages Programs run much faster More powerful IDE Easier to support huge projects
5
Scala as a candidate
Goal statically typed JVM-targeted concise language
Scala too complicated too implicit too difficult to create a good IDE
6
Era of new industrial languages
Ceylon Red Hat / Jboss (April 2011) Scala Typesafe (May 2011) Kotlin JetBrains (July 2011) xTend Eclipse / itemis (November 2011)
7
Kotlin “Hello, world”
fun main(args : Array<String>) {
Greeter().greet()
}
class Greeter(name : String = "world") {
val greeting = "Hello, $name!"
fun greet() {
println(greeting)
}
}
8
Problems and Solutions
Extending Existing APIs Handling Absent Values Case Analysis Multiple Implementation Inheritance Collection transformation Variance of Generic Types Builders
9
Extending Existing APIs
10
Regular expression example
Java
Pattern p = Pattern.compile("\\d*");
Matcher m = p.matcher("123");
if (m.find())
String result = m.group();
Scala
val r = "\\d*".r
val result = r.findFirstIn("123")
11
Scala: implicit conversions
val r = "\\d*".r
trait StringOps {
...
def r: Regex = new Regex(toString)
}
implicit def augmentString(x: String)
= new StringOps(x)
12
Scala: implicit conversions
val r = augmentString("\\d*").r
trait StringOps {
...
def r: Regex = new Regex(toString)
}
implicit def augmentString(x: String)
= new StringOps(x)
13
Scala: implicit conversions
val r = "\\d*".r
Conversion to 'StringOps' class: implicit requires a wrapper for each invocation
14
Functionality extension
Java
Collections.sort(list, comparator)
Scala / Kotlin
list.sort(comparator)
'sort' is not declared in java.util.List 'sort' can be autocompleted
15
Kotlin: extension functions
list.sort(comparator)
fun <T> List<T>.sort(c: Comparator<T>) {
...
}
16
Iterator for String
for (c in “abc”) { println(c)}
17
Iterator for String
for (c in “abc”) { println(c)}
class StringIterator(val s: String) : Iterator<Char> { private var i = 0 override fun next() = s[i++] override fun hasNext() = i < s.size}
18
Iterator for String
for (c in “abc”) { println(c)}
fun String.iterator() = StringIterator(this)
19
Extension functions
fun <T> List<T>.sort(c:
Comparator<T>) {...}
fun String.iterator() =
StringIterator(this)
non-virtual compile to a static function
20
Extending APIs
Scala implicit overhead on wrappers
Kotlin functionality cannot be inherited
21
Handling Absent Values
22
Java NPE problem
if (order.getCustomer(). //NPE
getInfo().getAge() >
limits.getMinLegalAge()) {
...
}
23
Java: @Nullable, @NotNull
@NotNull Customer getCustomer() {
...
return null; //warning, assertion
}
@Nullable Customer getCustomer() {...}
getCustomer().getInfo() //warning, NPE
24
Scala: Option type
def getCustomer() : Option[Customer] {…}
order.getCustomer match {
case Some(customer) =>
Some(customer.getInfo)
case None => None
}
25
Scala: Option type
def getCustomer() : Option[Customer] {…}
order.getCustomer match {
case Some(customer) =>
Some(customer.getInfo)
case None => None
}
order.getCustomer.map(_.getInfo)
26
Scala: Option type
def getCustomer() : Option[Customer] {
...
return null //no error
}
27
Scala: Option type
def getCustomer() : Option[Customer] order.getCustomer.map(_.getInfo).
map(_.getAge)
extra objects, classes are created: Some(customer), Some(info), Some(age) classes for function literals objects for function literals
inconvenient for debugging
28
Kotlin: nullable types
fun getCustomer() : Customer? {
...
return null
}
fun getCustomer() : Customer {
...
return null //error
}
29
Kotlin: nullable types
fun getCustomer() : Customer?
getCustomer().getInfo() error
getCustomer()?.getInfo() ok
30
Kotlin: nullable types
fun getCustomer() : Customer?
getCustomer().getInfo() error
getCustomer()?.getInfo() // Info?
31
Kotlin: nullable types
fun getCustomer() : Customer?
getCustomer()?.getInfo() // Info?
val customer = getCustomer()
if (customer != null)
customer.getInfo() // Info
32
Call chains
Java
order.getCustomer().getInfo().getAge()
Scala
order.getCustomer.map(_.getInfo).
map(_.getAge) Kotlin
order.getCustomer()?.getInfo()?.getAge()
33
“If not null” check
Scala
opt foreach { value =>
operate(value)
}
Kotlin
if (value != null) {
operate(value)
}
34
Java Interop
Scala
val files = new File("test").listFiles()
println(files.length) //NPE
Kotlin
val files = File("test").listFiles()
println(files.length) //doesn't compile
println(files?.size ?: "no files")
println(files!!.size) //NPE
35
Kotlin & Java interop
@NotNull, @Nullable annotations
“alternative headers”
package java.util
public trait List<E> : java.util.Collection<E> {
...
fun listIterator() : java.util.ListIterator<E>
}
36
Handling absent values
Scala overhead
Kotlin inconvenient Java interop without alternative
headers or annotations
37
Case Analysis
38
Scala: pattern matching
sealed trait Expr
case class Num(value: Int) extends Expr
case class Sum(left: Expr, right: Expr) extends Expr
def eval(e: Expr) : Int =
e match {
●
case Num(v) => v
case Sum(l, r) => eval(l) + eval(r) }
39
Kotlin: smart casts
trait Expr
class Number(val value: Int) : Expr
class Sum(val left: Expr, val right: Expr): Exprfun eval(e: Expr) : Int {
if (e is Number)
return e.value //smart cast
if (e is Sum) return eval(e.left) + eval(e.right)
throw IllegalArgumentException( “Unknown expression $e”)}
40
Kotlin: smart casts
trait Expr
class Num(val value: Int) : Expr
class Sum(val left: Expr, val right: Expr): Exprfun eval(e: Expr) : Int =
when (e) {
is Num > e.value
is Sum > eval(e.left) + eval(e.right)
else > throw IllegalArgumentException( “Unknown expression $e”) }
41
Multiple Implementation Inheritance
42
trait A { val a = print("A")}
trait B { val b = print("B")}
class C extends B with A {}
new C()
Scala traits
43
trait A { val a = print("A")}
trait B { val b = print("B")}
class C extends B with A {}
new C() // prints BA
Scala traits
44
trait A { val a = print("A")}
trait B extends A { val b = print("B")}
class C extends B with A {}
new C()
Scala traits
45
trait A { val a = print("A")}
trait B extends A { val b = print("B")}
class C extends B with A {}
new C() // prints AB
Scala traits
46
Scala traits
trait A { def foo()}
trait B extends A { override def foo() = "B"}
class C extends B {}
new C().foo() //"B"
47
Scala traits
trait A { def foo()}
trait B extends A { override def foo() = "B"}
trait D extends A { override def foo() = "D"}
class C extends B with D {}
new C().foo() //"D"
48
Kotlin traits
are more like Java interfaces methods can have bodies
no state no linearization
49
Kotlin traits
trait A { fun foo() = println("A")}
trait B { fun foo() = println("B")}
class C : B, A {} //doesn't compile
50
Kotlin traits
trait A { fun foo() = println("A")}
trait B { fun foo() = println("B")}
class C : B, A { override fun foo() { super<B>.foo() super<A>.foo() }}
51
Collection transformation
52
Scala collections
Set(1, 2, 3).map(_ * 0) Set(0)→
"abc".map(_.toUpper) → "ABC"
53
Scala collections
Set(1, 2, 3).map(_ * 0) Set(0)→
"abc".map(_.toUpper) → "ABC"
trait TraversableLike[+A, +Repr] {
def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That
}
54
Kotlin approach
'map', 'filter' always return immutable list
55
Kotlin approach
'map', 'filter' always return immutable list
hashSet(1, 2, 3).map {(i: Int) > i * 0} List(0, 0, 0)→
56
Kotlin approach
"abc".map {(c: Char) > c.toUpper} → "ABC"
fun String.map( f : (Char) > Char) : String
57
Lazy computations
Iterators are lazy set.iterator().map { … }.filter { … }
58
Lazy computations
Iterators are lazy set.iterator().map { … }.filter { … }
Iterables are not lazy val lazySet = set.lazyMap { … }
lazySet().filter { … }
lazySet().filter { … }
59
Variance of Generic Types
60
Scala. Declaration site variance
class List[+T] {
//only produces T
def head() : T
def tail() : List[T]
}
class Comparable[T] {
//only consumes T
def compare(t1 : T, t2: T)
}
61
Kotlin. Declaration site variance
class List<out T> {
//only produces T
fun head() : T
fun tail() : List[T]
}
class Comparable<in T> {
//only consumes T
fun compare(t1 : T, t2: T)
}
62
Use-site variance
fun <T> copy(from: Set<T>, to: Set<T>) {
...
}
copy(numbers, objects)
63
Kotlin. Use-site variance
fun <T> copy(from: List<out T>, to: List<T>) {
...
}
copy(numbers, objects)
64
Kotlin. Use-site variance
fun <T> copy(from: List<out T>, to: List<T>) {
from.add(t) //error
...
}
copy(numbers, objects)
65
Scala. Use-site variance
def copy[T](from: Set[_ <: T], to: Set[T]) {
...
}
copy(numbers, objects)
66
Scala. Existential types
def copy[T](from:
Set[X] forSome { type X <: T }, to: Set[T]) {
...
}
copy(numbers, objects)
67
Builders
68
Builders in Groovy
html { head { title "XML encoding with Groovy" }
body { h1 "XML encoding with Groovy" p "this format can be used as an alternative markup to XML" /* an element with attributes and text content */ ahref:'http://groovy.codehaus.org'["Groovy"] }}
69
Builders in Kotlin
html { head { title { + "XML encoding with Kotlin" } }
body { h1 { + "XML encoding with Kotlin" } p { + "this format this format is now typesafe" }
/* an element with attributes and text content */ a(href = "http://kotlin.jetbrains.org")["Kotlin"] }}
70
Builders: Implementation Function definition
fun html(init : HTML.() > Unit) : HTML {
val html = HTML()
html.init()
return html
}
Usage
html {
this.head { ... }
}
71
Builders: Implementation Function definition
fun html(init : HTML.() > Unit) : HTML {
val html = HTML()
html.init()
return html
}
Usage
html {
head { ... }
}
72
Builders: Implementation
class Tag(val name : String) : Element { val children = ArrayList<Element>() val attributes = HashMap<String, String>()} class TagWithText(name : String) : Tag(name) { fun String.plus() { children.add(TextElement(this)) }} class HTML() : Tag("html") { fun head(init : Head.() > Unit) { } fun body(init : Body.() > Unit) { }}
73
Builders in Kotlin
html { head { title { + "XML encoding with Kotlin" } }
body { h1 { + "XML encoding with Kotlin" } p { + "this format this format is now typesafe" }
/* an element with attributes and text content */ a(href = "http://kotlin.jetbrains.org")["Kotlin"] }}
74
Resources
Home page
http://kotlin.jetbrains.org
Web Demo
http://kotlindemo.jetbrains.com
Blog
http://blog.jetbrains.com/kotlin
Forum
Kotlin at http://devnet.jetbrains.com
75
Interesting links
Marius Eriksen “Effective Scala” http://twitter.github.com/effectivescala/
Yang Zhang “True Scala complexity” http://yz.mit.edu/wp/truescalacomplexity/
Joshua Suereth D. “Scala in Depth”http://www.amazon.com/ScalaDepthJoshuaSuerethD/dp/1935182706
Thank you!