Last active
February 22, 2021 09:13
-
-
Save bond15/84028e0b50c2f47753626b10a74a15c4 to your computer and use it in GitHub Desktop.
early Algebraic Data Types in Java (semicolons in 2021.. lol ;))
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package adt; | |
public class ADT { | |
// sealed is an experimental feature (requrires feature preview flag) of Java 15 | |
public sealed interface Expr | |
permits Const, Plus, Times { | |
} | |
// records in Java 15 | |
// records are Scala's Case Class (I'll admit Record is a much better and more accurate name!) | |
record Constant(int i) implements Expr{} | |
record Plus(Expr l, Expr r) implements Expr{} | |
record Time(Expr l, Expr r) implements Expr{} | |
public static void main(String args[]) { | |
// notice how their records require `new` (you can omit this in | |
// scala Case Classes for cleaner expression building) | |
Expr e = new Plus(new Constant(8), new Constant(9)); | |
try { | |
eval(e); | |
} catch (Exception ex){ | |
System.out.println("I am weak"); | |
} | |
} | |
// This shows some of their first steps towards pattern matching | |
// The syntax is less than great but it does abstract away the typical | |
// Instance-of-then-cast idiom that java programers use daily with this new | |
// infix `instanceof` operator. Useful but no exhaustivness checking. | |
public static int eval(Expr e) throws Exception{ | |
if (e instanceof Const c) return c.i(); | |
// 'pattern guard' | |
if (e instanceof Const c && c > 42) { System.out.prinln("42 is cool"); c.i(); } | |
else if (e instanceof Plusp) return eval(p.l()) + eval(p.r()); | |
else if (e instanceof Timest) return eval(t.l()) + eval(t.r()); | |
else throw new Exception("i dont have exhaustivness checking"); | |
} | |
// not yet.. :/ | |
// This may or may not be in Java 17? | |
// I think they may try for exhaustive case checking though | |
// http://openjdk.java.net/jeps/8213076 | |
/*return switch (e) { | |
case ConstantExpr i & i == 42 -> { System.out.prinln("42 is cool"); c.i(); }; | |
case ConstantExpr i -> i; | |
case PlusExpr l r -> eval(l) + eval(r); | |
case TimesExpr l r -> eval(l) * eval(r); | |
};*/ | |
// NOTE: traditionally java switch statements had 'fall through' semantics. now it supports both! | |
//http://openjdk.java.net/jeps/361 | |
//fall through | |
// hits cases 2,3, and default | |
public static void thing(){ | |
switch (2) { | |
case 1: | |
System.out.println(1); | |
break; | |
case 2: | |
System.out.println(2); | |
case 3: | |
System.out.println("oops i forgot to break!"); | |
default: | |
System.out.println("forgot to break again and now i've bottomed out in default"); | |
} | |
} | |
// only hits case 2 (SANE BEHAVIOR) | |
public static void thing2(){ | |
switch (2) { | |
case 1 -> | |
System.out.println(1); | |
case 2 -> | |
System.out.println(2); | |
case 3 -> | |
System.out.println("oops i forgot to break! JK!!!"); | |
default -> | |
System.out.println("forgot to break again and now i've bottomed out in default JK!!"); | |
} | |
} | |
} | |
/* | |
Vs Scala | |
object Adt{ | |
sealed trait Expr | |
case class Const(i: Integer) extends Expr | |
case class Plus(l: Expr, r: Expr) extends Expr | |
case class Mult(l: Expr, r: Expr) extends Expr | |
val expr: Expr = Mult(Plus(Const(1),Const(2)),Const(2)) | |
def eval: Expr => Int = e => e match { | |
case Const(i) => i | |
case Plus(l,r) => eval(l) + eval(r) | |
case Mult(l,r) => eval(l) * eval(r) | |
} | |
} | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment