/* * This example is modified from expr.kt to include a package * and to make eval(..) a static function of the Expr class * in that package. * * Since Kotlin does not support static class functions, * Expr.eval is wrapped in a compaion object, a gimmick: * https://kotlinlang.org/docs/reference/object-declarations.html#companion-objects */ // This works when compiled with kotlinc and run as a class file: // $ kotlinc expr1.kt // $ kotlin com.netfluke.calc.Expr1Kt // e is 5.0 , e1 is 6.0 , e2 is NaN, e3 is 7.0 // // For ADT rationale, see // https://medium.com/car2godevs/kotlin-adt-74472319962a // http://engineering.pivotal.io/post/algebraic-data-types-in-kotlin/ package com.netfluke.calc sealed class Expr { // abstract class, parent for all actual node types below companion object { 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 } } } 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() val e = Expr.eval( Sum( Const(2.0), Const(3.0) )) val e1 = Expr.eval( Sum( Const(1.0), Sum( Const(2.0), Const(3.0) ))) val e2 = Expr.eval( Sum( Const(1.0), Sum( Const(2.0), NotANumber ))) val e3 = Expr.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