Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

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";

Slide 14

Slide 14 text

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"

Slide 15

Slide 15 text

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";

Slide 16

Slide 16 text

…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"

Slide 17

Slide 17 text

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?

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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)

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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 }

Slide 28

Slide 28 text

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.

Slide 29

Slide 29 text

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!

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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.

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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 }

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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 }

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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)

Slide 38

Slide 38 text

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)

Slide 39

Slide 39 text

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 } } }

Slide 40

Slide 40 text

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)

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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; } }

Slide 44

Slide 44 text

shared, satisfies and actual? srsly

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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) { ... }

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

No content

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

No content