The Kotlin Programming Language, Svetlana Isakova

3,190
-1

Published on

Talk given by Svetlana Isakova at scaladev'12 (scaladev.ru)

Published in: Technology

The Kotlin Programming Language, Svetlana Isakova

  1. 1. The KotlinProgramming Language Svetlana Isakova
  2. 2. What? Who? Why? A modern language  Statically typed  Object-oriented  General-purpose Compiler  JVM byte code  JavaScript (not GWT) 2
  3. 3. What? Who? Why? A modern language  Statically typed  Object-oriented  General-purpose Developed by JetBrains  Open source  Intended for industrial use 3
  4. 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 4
  5. 5. Scala as a candidate Goal  statically typed  JVM-targeted  concise language Scala  too complicated  too implicit  too difficult to create a good IDE 5
  6. 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) 6
  7. 7. Kotlin “Hello, world” fun main(args : Array<String>) {     Greeter().greet() } class Greeter(name : String = "world") {     val greeting = "Hello, $name!"     fun greet() {         println(greeting)     } } 7
  8. 8. Problems and Solutions Extending Existing APIs Handling Absent Values Case Analysis Multiple Implementation Inheritance Collection transformation Variance of Generic Types Builders 8
  9. 9. Extending Existing APIs 9
  10. 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") 10
  11. 11. Scala: implicit conversionsval r = "d*".r trait StringOps {   ...  def r: Regex = new Regex(toString)} implicit def augmentString(x: String)                    = new StringOps(x) 11
  12. 12. Scala: implicit conversionsval r = augmentString("d*").r trait StringOps {   ...  def r: Regex = new Regex(toString)} implicit def augmentString(x: String)                    = new StringOps(x) 12
  13. 13. Scala: implicit conversions val r = "d*".r Conversion to StringOps class:  implicit  requires a wrapper for each invocation 13
  14. 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 14
  15. 15. Kotlin: extension functions list.sort(comparator) fun <T> List<T>.sort(c: Comparator<T>) {     ... } 15
  16. 16. Iterator for Stringfor (c in “abc”) {    println(c)}  16
  17. 17. Iterator for Stringfor (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} 17
  18. 18. Iterator for Stringfor (c in “abc”) {    println(c)}fun String.iterator() =                  StringIterator(this)  18
  19. 19. Extension functions fun <T> List<T>.sort(c:                Comparator<T>) {...} fun String.iterator() =                StringIterator(this)  non-virtual  compile to a static function 19
  20. 20. Extending APIs Scala  implicit  overhead on wrappers Kotlin  functionality cannot be inherited 20
  21. 21. Handling Absent Values 21
  22. 22. Java NPE problem if (order.getCustomer().       //NPE       getInfo().getAge() >           limits.getMinLegalAge()) {  ...  } 22
  23. 23. Java: @Nullable, @NotNull @NotNull Customer getCustomer() {    ...    return null; //warning, assertion } @Nullable Customer getCustomer() {...} getCustomer().getInfo() //warning, NPE 23
  24. 24. Scala: Option type def getCustomer() : Option[Customer]  {…}   order.getCustomer match {    case Some(customer) =>                 Some(customer.getInfo)    case None => None }     24
  25. 25. Scala: Option type def getCustomer() : Option[Customer]  {…}   order.getCustomer match {    case Some(customer) =>                 Some(customer.getInfo)    case None => None }   order.getCustomer.map(_.getInfo) 25
  26. 26. Scala: Option type def getCustomer() : Option[Customer] {   ...   return null //no error } 26
  27. 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 27
  28. 28. Kotlin: nullable types fun getCustomer() : Customer? {      ...     return null } fun getCustomer() : Customer {     ...     return null //error } 28
  29. 29. Kotlin: nullable types fun getCustomer() : Customer?  getCustomer().getInfo()   error   getCustomer()?.getInfo()   ok     29
  30. 30. Kotlin: nullable types fun getCustomer() : Customer?  getCustomer().getInfo()   error   getCustomer()?.getInfo()   // Info?   30
  31. 31. Kotlin: nullable types fun getCustomer() : Customer?    getCustomer()?.getInfo()   // Info?   val customer = getCustomer() if (customer != null)      customer.getInfo()       // Info 31
  32. 32. Call chains Java order.getCustomer().getInfo().getAge()   Scala order.getCustomer.map(_.getInfo).                          map(_.getAge) Kotlin order.getCustomer()?.getInfo()?.getAge() 32
  33. 33. “If not null” check Scala opt foreach { value =>    operate(value) } Kotlin if (value != null) {    operate(value) } 33
  34. 34. Java Interop Scala val files = new File("test").listFiles() println(files.length) //NPE Kotlin val files = File("test").listFiles() println(files.length) //doesnt compile println(files?.size ?: "no files") println(files!!.size) //NPE 34
  35. 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> } 35
  36. 36. Handling absent values Scala  overhead Kotlin  inconvenient Java interop without alternative headers or annotations 36
  37. 37. Case Analysis 37
  38. 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) }             38
  39. 39. Kotlin: smart casts  trait Expr  class Number(val value: Int) : Expr class Sum(val left: Expr, val right: Expr):                                          Expr  fun 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”) } 39
  40. 40. Kotlin: smart casts  trait Expr  class Num(val value: Int) : Expr class Sum(val left: Expr, val right: Expr):                                          Expr  fun eval(e: Expr) : Int =     when (e) {      is Num ­> e.value       is Sum ­> eval(e.left) + eval(e.right)     else ­> throw IllegalArgumentException(                      “Unknown expression $e”)   } 40
  41. 41. MultipleImplementationInheritance 41
  42. 42. Scala traitstrait A {  val a = print("A")}trait B {  val b = print("B")}class C extends B with A {}new C()  42
  43. 43. Scala traitstrait A {  val a = print("A")}trait B {  val b = print("B")}class C extends B with A {}new C() // prints BA 43
  44. 44. Scala traitstrait A {  val a = print("A")}trait B extends A {  val b = print("B")}class C extends B with A {}new C()  44
  45. 45. Scala traitstrait A {  val a = print("A")}trait B extends A {  val b = print("B")}class C extends B with A {}new C() // prints AB 45
  46. 46. Scala traitstrait A {  def foo()}trait B extends A {  override def foo() = "B"}class C extends B {}new C().foo()  //"B" 46
  47. 47. Scala traitstrait 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" 47
  48. 48. Kotlin traits are more like Java interfaces methods can have bodies no state no linearization 48
  49. 49. Kotlin traitstrait A {    fun foo() = println("A")} trait B {    fun foo() = println("B")} class C : B, A {} //doesnt compile                 49
  50. 50. Kotlin traitstrait A {    fun foo() = println("A")} trait B {    fun foo() = println("B")} class C : B, A {    override fun foo() {        super<B>.foo()        super<A>.foo()    }} 50
  51. 51. Collectiontransformation 51
  52. 52. Scala collections Set(1, 2, 3).map(_ * 0) →  Set(0) "abc".map(_.toUpper)   →    "ABC" 52
  53. 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  } 53
  54. 54. Kotlin approach map, filter always return immutable list 54
  55. 55. Kotlin approach map, filter always return immutable list hashSet(1, 2, 3).map                      {(i: Int) ­> i * 0}                               → List(0, 0, 0) 55
  56. 56. Kotlin approach "abc".map {(c: Char) ­>                          c.toUpper}   →     "ABC" fun String.map(                             f : (Char) ­> Char) : String 56
  57. 57. Lazy computations Iterators are lazy set.iterator().map { … }.filter { … } 57
  58. 58. Lazy computations Iterators are lazy set.iterator().map { … }.filter { … } Iterables are not lazy val lazySet = set.lazyMap { … } lazySet().filter { … } lazySet().filter { … } 58
  59. 59. Varianceof Generic Types 59
  60. 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) } 60
  61. 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) } 61
  62. 62. Use-site variancefun <T> copy(from: Set<T>,                                to: Set<T>) {  ...}copy(numbers, objects) 62
  63. 63. Kotlin. Use-site variancefun <T> copy(from: List<out T>,                            to: List<T>) {  ...}copy(numbers, objects) 63
  64. 64. Kotlin. Use-site variancefun <T> copy(from: List<out T>,                            to: List<T>) {  from.add(t) //error  ...}copy(numbers, objects)  64
  65. 65. Scala. Use-site variancedef copy[T](from: Set[_ <: T],                              to: Set[T]) {  ...}copy(numbers, objects) 65
  66. 66. Scala. Existential typesdef copy[T](from:     Set[X] forSome { type X <: T },                      to: Set[T]) {  ...}copy(numbers, objects) 66
  67. 67. Builders 67
  68. 68. Builders in Groovyhtml {   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"]   }} 68
  69. 69. Builders in Kotlinhtml {   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"]   }} 69
  70. 70. Builders: Implementation Function definition fun html(init : HTML.() ­> Unit) : HTML {     val html = HTML()     html.init()     return html } Usage html {     this.head { ... } } 70
  71. 71. Builders: Implementation Function definition fun html(init : HTML.() ­> Unit) : HTML {     val html = HTML()     html.init()     return html } Usage html {     head { ... } } 71
  72. 72. Builders: Implementationclass 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) { } 72}
  73. 73. Builders in Kotlinhtml {   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"]   }} 73
  74. 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 74
  75. 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 75
  76. 76. Thank you!

×