Skip to content

Instantly share code, notes, and snippets.

@bond15
Last active February 22, 2021 09:13
Show Gist options
  • Save bond15/84028e0b50c2f47753626b10a74a15c4 to your computer and use it in GitHub Desktop.
Save bond15/84028e0b50c2f47753626b10a74a15c4 to your computer and use it in GitHub Desktop.
early Algebraic Data Types in Java (semicolons in 2021.. lol ;))
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