// From https://kotlinlang.org/docs/reference/whatsnew11.html, // also https://kotlinlang.org/docs/reference/sealed-classes.html // This works when compiled with kotlinc and run as a class file: /// $ kotlinc expr.kt // $ kotlin ExprKt // e is 5.0 , e1 is 6.0 , e2 is NaN, e3 is 7.0 // // but fails when :load-ed from kotlinc-jvm (probably because // there compiling goes by line by line: // "error: this type is sealed, so it can be inherited by only its own nested classes or objects" // For ADT rationale, see // https://medium.com/car2godevs/kotlin-adt-74472319962a // http://engineering.pivotal.io/post/algebraic-data-types-in-kotlin/ sealed class Expr // base class, absract parent of all others data class Const(val number: Double) : Expr() // pretty-printing, equality, ... data class Sum(val e1: Expr, val e2: Expr) : Expr() // data class Prod(val e1: Expr, val e2: Expr) : Expr() object NotANumber : Expr() // recursive arithmeic eval fun eval(expr: Expr): Double = when (expr) { is Const -> expr.number is Sum -> eval(expr.e1) + eval(expr.e2) is Prod -> eval(expr.e1) * eval(expr.e2) NotANumber -> Double.NaN } val e = eval( Sum( Const(2.0), Const(3.0) )) val e1 = eval( Sum( Const(1.0), Sum( Const(2.0), Const(3.0) ))) val e2 = eval( Sum( Const(1.0), Sum( Const(2.0), NotANumber ))) val e3 = eval( Sum( Const(1.0), Prod( Const(2.0), Const(3.0) ))) fun main(args: Array) { println("e is $e , e1 is ${e1} , e2 is ${e2}, e3 is ${e3}") } // e is 5.0 , e1 is 6.0 , e2 is NaN, e3 is 7.0