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. 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. Java is everywhere ▶ On the web ▶ On your

    phone ▶ On embedded devices
  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. Now for the bad sides ▶ Limited expressivity ▶ Limited

    type-inference ▶ Excessive verbosity ▶ Backwards compatibility is holding it back
  5. Type Inference val i = 10; val m = new

    HashMap<String,String>();
  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. 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. 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. None
  10. Checked Exceptions public FileInputStream(String name) throws FileNotFoundException No other mainstream

    programming language has implemented it later
  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
  12. None
  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";
  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"
  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";
  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"
  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?
  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
  19. Operator overloading is awesome ▶ but developers are idiots4 4scala-graph.org

  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)
  21. Hello World fun main(args: Array<String>) { println("Hello World") }

  22. Type Inference val aNumber = 10 equivalent to final int

    aNumber = 10; // notice the final modifier here
  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
  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
  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
  26. Extension Functions fun String.reverse() { return StringBuilder(this).reverse().toString() } or simply

    fun String.reverse() = StringBuilder(this).reverse().toString()
  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 }
  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.
  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!
  30. Inheritance open class Animal(name: String) { open fun eat(Food food)

    = "nom nom" } class Dog(name: String) : Animal(name) { fun bark() = "woof!" }
  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.
  32. Smart Casts if (lassie is Dog) { println(lassie.bark()) // compiler

    knows about bark() }
  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 }
  34. Native Singleton Objects object MainApp : Application { fun hello()

    = "hello" } ... println(MainApp.hello()) Use case: static methods
  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 }
  36. Delegated Properties class User(val map: Map<String, Any?>) { val name:

    String by Delegates.mapVal(map) val age: Int by Delegates.mapVal(map) }
  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)
  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)
  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 } } }
  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)
  41. Hello World void hello() { print("hello world"); }

  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
  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; } }
  44. shared, satisfies and actual? srsly

  45. Properties ▶ Properties value count = 0; shared variable value

    hello = "Hello"; // I CAN HAZ MODIFIERS ▶ automatic getters and setters ▶ getHello$() and setHello$() ▶ no, really
  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) { ... }
  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> { ... }
  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
  49. None
  50. Enumerated Subtypes (Algebraic Data Types) abstract class Node() of Leaf

    | Branch {} ... Node node = ... ; switch (node) case (is Leaf) { ... } case (is Branch) { .... }
  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
  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
  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
  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
  55. None