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

Post on 10-May-2015

7.143 views 5 download

Tags:

description

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

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

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 type­safe" }

      /* 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 type­safe" }

      /* 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://kotlin­demo.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/true­scala­complexity/

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

Thank you!