Светлана Исакова «Язык Kotlin»

76
The Kotlin Programming Language Svetlana Isakova

description

Язык Kotlin, зачем он нужен, и его концептуальные отличия от Scala. Презентация доступна на странице проекта: http://scaladev.ru

Transcript of Светлана Исакова «Язык Kotlin»

Page 1: Светлана Исакова «Язык Kotlin»

The Kotlin Programming Language

Svetlana Isakova

Page 2: Светлана Исакова «Язык Kotlin»

2

What? Who? Why?

A modern language Statically typed Object-oriented General-purpose

Compiler

JVM byte code JavaScript (not GWT)

Page 3: Светлана Исакова «Язык Kotlin»

3

What? Who? Why?

A modern language Statically typed Object-oriented General-purpose

Developed by JetBrains

Open source Intended for industrial use

Page 4: Светлана Исакова «Язык Kotlin»

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

Page 5: Светлана Исакова «Язык Kotlin»

5

Scala as a candidate

Goal statically typed JVM-targeted concise language

Scala too complicated too implicit too difficult to create a good IDE

Page 6: Светлана Исакова «Язык Kotlin»

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)

Page 7: Светлана Исакова «Язык Kotlin»

7

Kotlin “Hello, world”

fun main(args : Array<String>) {

    Greeter().greet()

}

class Greeter(name : String = "world") {

    val greeting = "Hello, $name!"

    fun greet() {

        println(greeting)

    }

}

Page 8: Светлана Исакова «Язык Kotlin»

8

Problems and Solutions

Extending Existing APIs Handling Absent Values Case Analysis Multiple Implementation Inheritance Collection transformation Variance of Generic Types Builders

Page 9: Светлана Исакова «Язык Kotlin»

9

Extending Existing APIs

Page 10: Светлана Исакова «Язык Kotlin»

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")

Page 11: Светлана Исакова «Язык Kotlin»

11

Scala: implicit conversions

val r = "\\d*".r 

trait StringOps { 

  ...

  def r: Regex = new Regex(toString)

implicit def augmentString(x: String)

                    = new StringOps(x)

Page 12: Светлана Исакова «Язык Kotlin»

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)

Page 13: Светлана Исакова «Язык Kotlin»

13

Scala: implicit conversions

val r = "\\d*".r

Conversion to 'StringOps' class: implicit requires a wrapper for each invocation

Page 14: Светлана Исакова «Язык Kotlin»

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

Page 15: Светлана Исакова «Язык Kotlin»

15

Kotlin: extension functions

list.sort(comparator)

fun <T> List<T>.sort(c: Comparator<T>) {

    ...

}

Page 16: Светлана Исакова «Язык Kotlin»

16

Iterator for String

for (c in “abc”) {    println(c)}

 

Page 17: Светлана Исакова «Язык Kotlin»

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}

Page 18: Светлана Исакова «Язык Kotlin»

18

Iterator for String

for (c in “abc”) {    println(c)}

fun String.iterator() =                  StringIterator(this)

 

Page 19: Светлана Исакова «Язык Kotlin»

19

Extension functions

fun <T> List<T>.sort(c:

               Comparator<T>) {...}

fun String.iterator() =

               StringIterator(this)

non-virtual compile to a static function

Page 20: Светлана Исакова «Язык Kotlin»

20

Extending APIs

Scala implicit overhead on wrappers

Kotlin functionality cannot be inherited

Page 21: Светлана Исакова «Язык Kotlin»

21

Handling Absent Values

Page 22: Светлана Исакова «Язык Kotlin»

22

Java NPE problem

if (order.getCustomer().       //NPE

      getInfo().getAge() >

          limits.getMinLegalAge()) {

 ... 

}

Page 23: Светлана Исакова «Язык Kotlin»

23

Java: @Nullable, @NotNull

@NotNull Customer getCustomer() {

   ...

   return null; //warning, assertion

}

@Nullable Customer getCustomer() {...}

getCustomer().getInfo() //warning, NPE

Page 24: Светлана Исакова «Язык Kotlin»

24

Scala: Option type

def getCustomer() : Option[Customer] {…} 

order.getCustomer match {

   case Some(customer) =>

                Some(customer.getInfo)

   case None => None

 

Page 25: Светлана Исакова «Язык Kotlin»

25

Scala: Option type

def getCustomer() : Option[Customer] {…} 

order.getCustomer match {

   case Some(customer) =>

                Some(customer.getInfo)

   case None => None

order.getCustomer.map(_.getInfo)

Page 26: Светлана Исакова «Язык Kotlin»

26

Scala: Option type

def getCustomer() : Option[Customer] {

  ...

  return null //no error

}

Page 27: Светлана Исакова «Язык Kotlin»

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

Page 28: Светлана Исакова «Язык Kotlin»

28

Kotlin: nullable types

fun getCustomer() : Customer? { 

    ...

    return null

}

fun getCustomer() : Customer {

    ...

    return null //error

}

Page 29: Светлана Исакова «Язык Kotlin»

29

Kotlin: nullable types

fun getCustomer() : Customer? 

getCustomer().getInfo()   error 

getCustomer()?.getInfo()   ok 

 

Page 30: Светлана Исакова «Язык Kotlin»

30

Kotlin: nullable types

fun getCustomer() : Customer? 

getCustomer().getInfo()   error 

getCustomer()?.getInfo()   // Info? 

Page 31: Светлана Исакова «Язык Kotlin»

31

Kotlin: nullable types

fun getCustomer() : Customer? 

 

getCustomer()?.getInfo()   // Info? 

val customer = getCustomer()

 if (customer != null) 

  customer.getInfo()       // Info

Page 32: Светлана Исакова «Язык Kotlin»

32

Call chains

Java

order.getCustomer().getInfo().getAge() 

Scala

order.getCustomer.map(_.getInfo).

                         map(_.getAge) Kotlin

order.getCustomer()?.getInfo()?.getAge()

Page 33: Светлана Исакова «Язык Kotlin»

33

“If not null” check

Scala

opt foreach { value =>

   operate(value)

}

Kotlin

if (value != null) {

   operate(value)

}

Page 34: Светлана Исакова «Язык Kotlin»

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

Page 35: Светлана Исакова «Язык Kotlin»

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>

}

Page 36: Светлана Исакова «Язык Kotlin»

36

Handling absent values

Scala overhead

Kotlin inconvenient Java interop without alternative

headers or annotations

Page 37: Светлана Исакова «Язык Kotlin»

37

Case Analysis

Page 38: Светлана Исакова «Язык Kotlin»

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)            }

Page 39: Светлана Исакова «Язык Kotlin»

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”)}

Page 40: Светлана Исакова «Язык Kotlin»

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”)  }

Page 41: Светлана Исакова «Язык Kotlin»

41

Multiple Implementation Inheritance

Page 42: Светлана Исакова «Язык Kotlin»

42

trait A {  val a = print("A")}

trait B {  val b = print("B")}

class C extends B with A {}

new C() 

Scala traits

Page 43: Светлана Исакова «Язык Kotlin»

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

Page 44: Светлана Исакова «Язык Kotlin»

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

Page 45: Светлана Исакова «Язык Kotlin»

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

Page 46: Светлана Исакова «Язык Kotlin»

46

Scala traits

trait A {  def foo()}

trait B extends A {  override def foo() = "B"}

class C extends B {}

new C().foo()  //"B"

Page 47: Светлана Исакова «Язык Kotlin»

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"

Page 48: Светлана Исакова «Язык Kotlin»

48

Kotlin traits

are more like Java interfaces methods can have bodies

no state no linearization

Page 49: Светлана Исакова «Язык Kotlin»

49

Kotlin traits

trait A {    fun foo() = println("A")} 

trait B {    fun foo() = println("B")} 

class C : B, A {} //doesn't compile                

Page 50: Светлана Исакова «Язык Kotlin»

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()    }}

Page 51: Светлана Исакова «Язык Kotlin»

51

Collection transformation

Page 52: Светлана Исакова «Язык Kotlin»

52

Scala collections

Set(1, 2, 3).map(_ * 0)    Set(0)→

"abc".map(_.toUpper)        → "ABC"

Page 53: Светлана Исакова «Язык Kotlin»

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 

}

Page 54: Светлана Исакова «Язык Kotlin»

54

Kotlin approach

'map', 'filter' always return immutable list

Page 55: Светлана Исакова «Язык Kotlin»

55

Kotlin approach

'map', 'filter' always return immutable list

hashSet(1, 2, 3).map                     {(i: Int) ­> i * 0}                                List(0, 0, 0)→

Page 56: Светлана Исакова «Язык Kotlin»

56

Kotlin approach

"abc".map {(c: Char) ­>                         c.toUpper}        → "ABC"

fun String.map(                            f : (Char) ­> Char) : String

Page 57: Светлана Исакова «Язык Kotlin»

57

Lazy computations

Iterators are lazy set.iterator().map { … }.filter { … }

Page 58: Светлана Исакова «Язык Kotlin»

58

Lazy computations

Iterators are lazy set.iterator().map { … }.filter { … }

Iterables are not lazy val lazySet = set.lazyMap { … }

lazySet().filter { … }

lazySet().filter { … }

Page 59: Светлана Исакова «Язык Kotlin»

59

Variance of Generic Types

Page 60: Светлана Исакова «Язык Kotlin»

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)

}

Page 61: Светлана Исакова «Язык Kotlin»

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)

}

Page 62: Светлана Исакова «Язык Kotlin»

62

Use-site variance

fun <T> copy(from: Set<T>,                                to: Set<T>) {

  ...

}

copy(numbers, objects)

Page 63: Светлана Исакова «Язык Kotlin»

63

Kotlin. Use-site variance

fun <T> copy(from: List<out T>,                            to: List<T>) {

  ...

}

copy(numbers, objects)

Page 64: Светлана Исакова «Язык Kotlin»

64

Kotlin. Use-site variance

fun <T> copy(from: List<out T>,                            to: List<T>) {

  from.add(t) //error

  ...

}

copy(numbers, objects) 

Page 65: Светлана Исакова «Язык Kotlin»

65

Scala. Use-site variance

def copy[T](from: Set[_ <: T],                              to: Set[T]) {

  ...

}

copy(numbers, objects)

Page 66: Светлана Исакова «Язык Kotlin»

66

Scala. Existential types

def copy[T](from:

     Set[X] forSome { type X <: T },                      to: Set[T]) {

  ...

}

copy(numbers, objects)

Page 67: Светлана Исакова «Язык Kotlin»

67

Builders

Page 68: Светлана Исакова «Язык Kotlin»

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"]   }}

Page 69: Светлана Исакова «Язык Kotlin»

69

Builders in Kotlin

html {   head {      title { + "XML encoding with Kotlin" }   }

   body {      h1 { + "XML encoding with Kotlin" }      p { + "this format this format is now type­safe" }

      /* an element with attributes and text content */      a(href = "http://kotlin.jetbrains.org")["Kotlin"]   }}

Page 70: Светлана Исакова «Язык Kotlin»

70

Builders: Implementation Function definition

fun html(init : HTML.() ­> Unit) : HTML {

    val html = HTML()

    html.init()

    return html

}

Usage

html {

    this.head { ... }

}

Page 71: Светлана Исакова «Язык Kotlin»

71

Builders: Implementation Function definition

fun html(init : HTML.() ­> Unit) : HTML {

    val html = HTML()

    html.init()

    return html

}

Usage

html {

    head { ... }

}

Page 72: Светлана Исакова «Язык Kotlin»

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) { }}

Page 73: Светлана Исакова «Язык Kotlin»

73

Builders in Kotlin

html {   head {      title { + "XML encoding with Kotlin" }   }

   body {      h1 { + "XML encoding with Kotlin" }      p { + "this format this format is now type­safe" }

      /* an element with attributes and text content */      a(href = "http://kotlin.jetbrains.org")["Kotlin"]   }}

Page 74: Светлана Исакова «Язык Kotlin»

74

Resources

Home page

http://kotlin.jetbrains.org

Web Demo

http://kotlin­demo.jetbrains.com

Blog

http://blog.jetbrains.com/kotlin

Forum

Kotlin at http://devnet.jetbrains.com

Page 75: Светлана Исакова «Язык Kotlin»

75

Interesting links

Marius Eriksen “Effective Scala” http://twitter.github.com/effectivescala/

Yang Zhang “True Scala complexity” http://yz.mit.edu/wp/true­scala­complexity/

Joshua Suereth D. “Scala in Depth”http://www.amazon.com/Scala­Depth­Joshua­Suereth­D/dp/1935182706

Page 76: Светлана Исакова «Язык Kotlin»

Thank you!