Kotlin & Ceylon — Modern Programming Languages for a Modern JVM

Kotlin & Ceylon — Modern Programming Languages for a Modern JVM

06af491f015c1278d8c650a2e8598162?s=128

Edoardo Vacchi

October 17, 2014
Tweet

Transcript

  1. 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
  2. 2.

    Java is everywhere ▶ On the web ▶ On your

    phone ▶ On embedded devices
  3. 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
  4. 4.

    Now for the bad sides ▶ Limited expressivity ▶ Limited

    type-inference ▶ Excessive verbosity ▶ Backwards compatibility is holding it back
  5. 5.

    Type Inference val i = 10; val m = new

    HashMap<String,String>();
  6. 6.

    Type Inference val i = 10; val m = new

    HashMap<String,String>(); In Java (6) we had to write int i = 10; Map<String,String> m = new HashMap<String,String>();
  7. 7.

    Type Inference (2) but you could easily write public class

    Maps { public static <T,U> Map<T,U> map() { return new HashMap<T,U>(); } } ... Map<String,String> m = map(); which would work as intended
  8. 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
  9. 9.
  10. 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
  11. 12.
  12. 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";
  13. 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"
  14. 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";
  15. 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"
  16. 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?
  17. 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
  18. 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)
  19. 22.

    Type Inference val aNumber = 10 equivalent to final int

    aNumber = 10; // notice the final modifier here
  20. 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
  21. 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
  22. 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
  23. 26.
  24. 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 }
  25. 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.
  26. 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!
  27. 30.

    Inheritance open class Animal(name: String) { open fun eat(Food food)

    = "nom nom" } class Dog(name: String) : Animal(name) { fun bark() = "woof!" }
  28. 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.
  29. 33.

    when trait BinTree<T> class Node<T>(val value: T, val left: BinTree<T>,

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

    Native Singleton Objects object MainApp : Application { fun hello()

    = "hello" } ... println(MainApp.hello()) Use case: static methods
  31. 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 }
  32. 36.

    Delegated Properties class User(val map: Map<String, Any?>) { val name:

    String by Delegates.mapVal(map) val age: Int by Delegates.mapVal(map) }
  33. 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)
  34. 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)
  35. 39.

    Type-Safe Builders (DSLs) fun result(args: Array<String>) = 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 } } }
  36. 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)
  37. 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
  38. 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; } }
  39. 45.

    Properties ▶ Properties value count = 0; shared variable value

    hello = "Hello"; // I CAN HAZ MODIFIERS ▶ automatic getters and setters ▶ getHello$() and setHello$() ▶ no, really
  40. 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) { ... }
  41. 47.

    Union and Intersection Types Person|Organization personOrOrganization = ... ; Printable&Sized&Persistent

    printableSizedPersistent = ... ; YSK: Java has them. But only for generics… class C<T extends Person | Organization & Something> { ... }
  42. 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
  43. 49.
  44. 50.

    Enumerated Subtypes (Algebraic Data Types) abstract class Node() of Leaf

    | Branch {} ... Node node = ... ; switch (node) case (is Leaf) { ... } case (is Branch) { .... }
  45. 51.

    Operator Overloading Through Interfaces ▶ Summable<X> supports the infix +

    operator (plus(X)), ▶ Comparable<X> supports the comparison operators (compare(X)), ▶ Correspondence supports the index operator, ▶ Ranged supports the segment and span operators
  46. 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
  47. 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
  48. 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
  49. 55.