$30 off During Our Annual Pro Sale. View Details »

Kotlin & Ceylon — Modern Programming Languages for a Modern JVM

Kotlin & Ceylon — Modern Programming Languages for a Modern JVM

Edoardo Vacchi

October 17, 2014
Tweet

More Decks by Edoardo Vacchi

Other Decks in Programming

Transcript

  1. Kotlin & Ceylon
    Modern Programming Languages for a Modern JVM
    Edoardo Vacchi
     @evacchi
    © D O R O Z H K I N A
    flic.kr/p/hx59k9

    View Slide

  2. Java is everywhere
    ▶ On the web
    ▶ On your phone
    ▶ On embedded devices

    View Slide

  3. Resistence is futile
    Like it or not, one day you will have to use Java
    ▶ Enterprise loves it
    ▶ Limited expressivity is a bless for maintenance
    ▶ It is extremely backwards compatible
    ▶ Lots of 1.4 code is still in the wild

    View Slide

  4. Now for the bad sides
    ▶ Limited expressivity
    ▶ Limited type-inference
    ▶ Excessive verbosity
    ▶ Backwards compatibility is holding it back

    View Slide

  5. Type Inference
    val i = 10;
    val m = new HashMap();

    View Slide

  6. Type Inference
    val i = 10;
    val m = new HashMap();
    In Java (6) we had to write
    int i = 10;
    Map m = new HashMap();

    View Slide

  7. Type Inference (2)
    but you could easily write
    public class Maps {
    public static Map map() { return new HashMap(); }
    }
    ...
    Map m = map();
    which would work as intended

    View Slide

  8. Politics has been holding it back
    Map m = someWeirdMethodCall();
    «the redundant type serves as valuable documentation […]
    the redundancy allows the programmer to declare the
    intended type, and thereby benefit from a cross check
    performed by the compiler 1»
    — Gilad Bracha
    1http:/
    /bugs.java.com/bugdatabase/view_bug.do?bug_id=4459053

    View Slide

  9. View Slide

  10. Checked Exceptions
    public FileInputStream(String name) throws FileNotFoundException
    No other mainstream programming language has
    implemented it later

    View Slide

  11. Java Collections
    ▶ Optional operations
    ▶ Basically Java way to say #fuckit
    boolean java.util.List#add(E e)
    ▶ Appends the specified element to the end of this list
    ▶ Throws UnsupportedOperationException if the add
    operation is not supported

    View Slide

  12. View Slide

  13. Another Example (properties)
    The dreaded JavaBeans convention:
    Person john = new Person("John Doe", "some street");
    String name = john.getName();
    john.setAddress("some other street");
    A feature we find in modern programming languages
    String name = person.name;
    person.address = "some address";

    View Slide

  14. Scala
    case class Person(name: String, var address: String)
    // generates the methods
    def name: String
    def address: String
    def address_=(address: String): String
    ...
    val john = Person("John Doe", "some street")
    val name = john.name
    john.address = "some other street"

    View Slide

  15. C#
    class Person
    {
    public string Name { get; }
    public string Address { get; set; }
    public Person(string name, string address) { ... }
    }
    ...
    var john = new Person("John Doe", "some street");
    string name = john.Name;
    john.Address = "some other street";

    View Slide

  16. …and, of course, Visual Basic 6
    Private m_Name As String
    Public Property Get Name() As String
    Name = m_Name
    End Property
    Public Property Let Name(ByVal s As String)
    m_Name = s
    End Property
    ...
    Dim name As String = person.Name
    person.Address = "some other street"

    View Slide

  17. Scala to the rescue!
    ▶ Scala is awesome
    ▶ statically typed, «feels dynamic» (Bruce Eckel)
    ▶ Scala has a vibrant community and it’s 10 year old
    ▶ It’s gaining traction in the industry (sort of)
    ▶ so, what’s wrong with Scala?

    View Slide

  18. Scala is not really interoperable
    ▶ You may try to convince me that it is simple, but if you
    have to deal with code like this2
    def map[B, That](f: A ⇒ B)(implicit bf: CanBuildFrom[Repr, B, That]): That
    …then you are actively scaring people away
    ▶ Try and invoke this from Java. It’s impossible
    ▶ SI-43893 Resolution: NOT A BUG
    2“The longest suicide note in history” http:/
    /stackoverflow.com/q/1722726
    3https:/
    /issues.scala-lang.org/browse/SI-4389

    View Slide

  19. Operator overloading is awesome
    ▶ but developers are idiots4
    4scala-graph.org

    View Slide

  20. Kotlin
    ▶ Developed by JetBrains
    ▶ (IntelliJ IDEA, PhpStorm, RubyMine…)
    ▶ Developed with enterprise in mind
    ▶ A better Java
    ▶ It takes hint from Scala, C#, Groovy
    ▶ (some Groovy devs are involved)
    ▶ Statically typed
    Milestone 9 out (v0.9 — Oct, 15th)

    View Slide

  21. Hello World
    fun main(args: Array) {
    println("Hello World")
    }

    View Slide

  22. Type Inference
    val aNumber = 10
    equivalent to
    final int aNumber = 10; // notice the final modifier here

    View Slide

  23. Nullable Types in Java
    ▶ Tony Hoare’s million dollar mistake (in Algol)
    ▶ The null reference
    ▶ There is nothing wrong with a bottom value
    ▶ The problem is null handling
    Equivalent to annotating your Java 85 code with @NotNull and
    @Nullable
    @NotNull Map<@NotNull String, @NotNull Person> myMap = new HashMap<>();
    5also possible with JetBrains’ own annotations from Java 6 onward

    View Slide

  24. Nullable Types in Java
    ▶ Tony Hoare’s million dollar mistake (in Algol)
    ▶ The null reference
    ▶ There is nothing wrong with a bottom value
    ▶ The problem is null handling
    Equivalent to annotating your Java 85 code with @NotNull and
    @Nullable
    @NotNull Map<@NotNull String, @NotNull Person> myMap = new HashMap<>();
    5also possible with JetBrains’ own annotations from Java 6 onward

    View Slide

  25. Nullable Types in Kotlin
    val s1: String = null // compiler error
    val s2: String? = null // compiles
    // nullable result
    val anUnsafeResult = someStringFunction()
    val c: Char? = anUnsafeResult?.charAt(0)
    // non-nullable result
    val aSafeResult = anotherStringFunction()
    val c2: Char = aSafeResult.charAt(0)
    // nullable result with default
    val c3: Char = anUnsafeResult ?: 'x' // default value

    View Slide

  26. Extension Functions
    fun String.reverse() {
    return StringBuilder(this).reverse().toString()
    }
    or simply
    fun String.reverse() = StringBuilder(this).reverse().toString()

    View Slide

  27. Function literals
    val numbers = listOf(1,2,3,4)
    val even = numbers filter { (x) -> x % 2 == 0 }
    or just
    val even = numbers filter { it % 2 == 0 }

    View Slide

  28. Data Classes in Kotlin
    data class Person(val name: String, var address: String)
    equals() and toString() are auto-generated
    val myFoo = Foo("John Doe", "was here") // no `new` here
    val theName = myFoo.name
    myFoo.address = "was there"
    ▶ getName(), getAddress() and setAddressString() are
    auto-generated for Java compatibility.

    View Slide

  29. Arguments
    fun foo(value: String, optionalValue: String = "default value") { ... }
    ...
    foo("bar")
    foo(value="my value", optionalValue="anotherValue")
    And it works for constructors, too. Goodbye, builder pattern!

    View Slide

  30. Inheritance
    open class Animal(name: String) {
    open fun eat(Food food) = "nom nom"
    }
    class Dog(name: String) : Animal(name) {
    fun bark() = "woof!"
    }

    View Slide

  31. Traits
    trait Animal {
    // abstract values are allowed, but state cannot be initialized
    val name: String
    // function bodies are allowed
    fun eat(Food food): String {
    return "nom nom"
    }
    }
    I hear you saying “that’s already in Java 8”. This is Java 6
    compatible, though.

    View Slide

  32. Smart Casts
    if (lassie is Dog) {
    println(lassie.bark()) // compiler knows about bark()
    }

    View Slide

  33. when
    trait BinTree
    class Node(val value: T, val left: BinTree, val right: BinTree): BinTree
    class Leaf(val value: T) : Node(value)
    ...
    fun depth(t: BinTree): Int =
    when (t) {
    is Leaf -> 1
    is Node -> max(path(t.left), path(t.right))
    else -> throw UnsupportedOperationException() // no other known types
    }

    View Slide

  34. Native Singleton Objects
    object MainApp : Application {
    fun hello() = "hello"
    }
    ...
    println(MainApp.hello())
    Use case: static methods

    View Slide

  35. Native Delegation
    trait Base {
    fun print()
    }
    class BaseImpl(val x : Int) : Base {
    override fun print() { print(x) }
    }
    class Derived(b : Base) : Base by b
    fun main() {
    val b = BaseImpl(10)
    Derived(b).print() // prints 10
    }

    View Slide

  36. Delegated Properties
    class User(val map: Map) {
    val name: String by Delegates.mapVal(map)
    val age: Int by Delegates.mapVal(map)
    }

    View Slide

  37. Operator Overloading
    by convention:
    Expression Translated to
    a + b a.plus(b)
    a - b a.minus(b)
    a * b a.times(b)
    a / b a.div(b)
    a % b a.mod(b)
    a..b a.rangeTo(b)

    View Slide

  38. Operator Overloading (2)
    Symbol Translated to
    a[i] a.get(i)
    a[i, j] a.get(i, j)
    a[i_1, ..., i_n] a.get(i_1, ..., i_n)
    a[i] = b a.set(i, b)
    a[i, j] = b a.set(i, j, b)
    a[i_1, ..., i_n] = b a.set(i_1, ..., i_n, b)

    View Slide

  39. Type-Safe Builders (DSLs)
    fun result(args: Array) =
    html {
    head { title {+"XML encoding with Kotlin"} }
    body {
    h1 {+"XML encoding with Kotlin"}
    p {+"this format can be used as an alternative markup to XML"}
    a(href = "http://jetbrains.com/kotlin") {+"Kotlin"}
    p {
    for (arg in args)
    +arg
    }
    }
    }

    View Slide

  40. Ceylon
    ▶ Red Hat / JBoss
    ▶ Project Lead: Gavin King (Hybernate, Seam)
    ▶ Another strongly, statically-typed programming language
    ▶ Interesting type system
    ▶ …brought to you in a somewhat weird syntax
    ▶ v1.1 out (Oct, 9th 2014)

    View Slide

  41. Hello World
    void hello() {
    print("hello world");
    }

    View Slide

  42. Classes
    class Counter(Integer initialValue=0) {
    variable value count = initialValue; //`value` auto infers type
    shared Integer currentValue {
    return count;
    }
    shared void increment() {
    count++;
    }
    }
    If you are wondering why shared you are not alone

    View Slide

  43. Inheritance
    interface Sized {
    shared formal Integer size;
    shared Boolean empty {
    return size==0;
    }
    }
    interface Printable {
    shared void printIt() { print(this); }
    }
    object empty satisfies Sized & Printable {
    shared actual Integer size { return 0; }
    }

    View Slide

  44. shared, satisfies and actual?
    srsly

    View Slide

  45. Properties
    ▶ Properties
    value count = 0;
    shared variable value hello = "Hello"; // I CAN HAZ MODIFIERS
    ▶ automatic getters and setters
    ▶ getHello$() and setHello$()
    ▶ no, really

    View Slide

  46. Annotations
    "The user login action"
    by ("Gavin King")
    throws (`class DatabaseException`,
    "if database access fails")
    see (`function LogoutAction.logout`)
    scope (session)
    action { description="Log In"; url="/login"; }
    shared deprecated
    void login(Request request, Response response) { ... }

    View Slide

  47. Union and Intersection Types
    Person|Organization personOrOrganization = ... ;
    Printable&Sized&Persistent printableSizedPersistent = ... ;
    YSK: Java has them. But only for generics…
    class C { ... }

    View Slide

  48. Nullable Types
    void hello(String? name) {
    if (exists name) {
    print("Hello, ``name``!");
    }
    else {
    print("Hello, world!");
    }
    }
    In Ceylon String? is a shorthand for String|Null

    View Slide

  49. View Slide

  50. Enumerated Subtypes
    (Algebraic Data Types)
    abstract class Node() of Leaf | Branch {}
    ...
    Node node = ... ;
    switch (node)
    case (is Leaf) { ... }
    case (is Branch) { .... }

    View Slide

  51. Operator Overloading
    Through Interfaces
    ▶ Summable supports the infix + operator (plus(X)),
    ▶ Comparable supports the comparison operators
    (compare(X)),
    ▶ Correspondence supports the index operator,
    ▶ Ranged supports the segment and span operators

    View Slide

  52. Native Module System
    ▶ Project Jigsaw, OSGi, JBoss Modules
    ▶ Ceylon produces modules natively
    ▶ .car files (basically .jar + extra metadata)
    ▶ Actually, Kotlin has an identical concept, but it is not yet
    released

    View Slide

  53. Roundup: Kotlin
    ▶ Overall, Kotlin feels like an incremental improvement over
    Java
    ▶ pretty true, you can basically mix them
    ▶ they will work almost seamlessly
    ▶ Most features are already in Java as “best practices” or
    idioms
    ▶ What Kotlin does is to raise them at the language level,
    with some sugar

    View Slide

  54. Roundup: Ceylon
    ▶ I have mixed feelings for Ceylon
    ▶ Interesting type system
    ▶ Elegant design
    ▶ Strange, arbitrary syntactic choices
    ▶ Interoperability Java → Ceylon is fine,
    ▶ Ceylon → Java: I had some problems

    View Slide

  55. View Slide