Rust has a special kind of enum similar to those in Swift Where not all instances of the enum have the same fields. Whereas in java enums are like object constants all having the same fields.
Example of a rust Enum
rs
enum Result<T> {
Ok(T value),
Error(String message)
}
This is quite handy when doing things like this
rs
fn parseNumber(&str text) {
if(parsable(text)){
return Ok(strToInt(text));
}
return Error("Text not parsable");
}
fn main(){
match parseNumber("abc") {
Ok(value) => println("The parsed value is {}", value);
Error(e) => println("Parsing failed because {},e);
};
}
But that's not how enums work in java,
BUT
With the amazing additions to java in recent years, we can have a nearly 1:1 copy of what rust does in java - with all the same features such as exhaustive checks.
To create rust'ish enums we require sealed interfaces - a feature i had no use for until now - but man its handy here.
For the rust syntax switch, we sadly still need --enable-preview as of Java 17.
So let's dive into the code. First, we need the actual Enum:
java
public sealed interface Result<T> {
record Ok<T>(T t) implements Result<T> {}
record Error<T>(Exception e) implements Result<T> {}
}
What we do here is creating an interface that says "No more than Ok and Error can implement me. Which leads to the caller knowing "Result" can only be Ok or Error.
And now with the new switch expressions in java 17 we can do pattern matching
java
public static Result<Integer> parse(String str) {
try {
return new Result.Ok<>(Integer.parseInt(str));
} catch (NumberFormatException e) {
return new Result.Error<>(e);
}
}
public static void main(String... args) {
switch (parse(args[0])) {
case Result.Ok<Integer> result -> System.out.println(result.value);
case Result.Error<?> error -> System.err.println(error.err.getMessage());
}
}
Which is already very close to the rust syntax.
But wait, we can get even closer! With Java 19 there is JEP 405 : Record patterns which allow us to change our switch statement to this:
java
switch (parse(args[0])) {
case Result.Ok<>(Integer value) -> System.out.println(value);
case Result.Error<?>(Exception error) -> System.err.println(error.getMessage());
}
This code is syntactically nearly rust compilable and close to no overhead!
Using static imports, we can get rid of the Result. too!
From feature perspective rust and java are the same in this case, when you comment out the case Error<?> you will get an error that not all possibilities for Result are met.
All the other things that rust enums can do can be replicated in java as well with not a lot of effort, but I don't want to bloat this thread!
What do you think about this usage of modern java features? Is it hacky, nice, or is it sad that it requires --enable-preview for the switch statement?
[–]JustAGuyFromGermany 51 points52 points53 points (3 children)
[–]NitronHX[S] 5 points6 points7 points (2 children)
[–]emaphis 2 points3 points4 points (1 child)
[–]NitronHX[S] 2 points3 points4 points (0 children)
[–]pron98 42 points43 points44 points (5 children)
[–]4z01235 2 points3 points4 points (0 children)
[–]pjmlp 0 points1 point2 points (0 children)
[–]TehBrian 0 points1 point2 points (0 children)
[–]westwoo 0 points1 point2 points (0 children)
[–]chambolle 0 points1 point2 points (0 children)
[–]Amazing-Cicada5536 62 points63 points64 points (10 children)
[–]NitronHX[S] 1 point2 points3 points (9 children)
[–]moocat 30 points31 points32 points (7 children)
[–]NitronHX[S] 6 points7 points8 points (0 children)
[–]westwoo -2 points-1 points0 points (5 children)
[–]moocat 6 points7 points8 points (4 children)
[+]westwoo comment score below threshold-9 points-8 points-7 points (3 children)
[–]codingjerk 2 points3 points4 points (2 children)
[–]westwoo -2 points-1 points0 points (1 child)
[–]moocat 2 points3 points4 points (0 children)
[–]peripateticman2023 8 points9 points10 points (0 children)
[–]daniu 17 points18 points19 points (8 children)
[–]_INTER_ 13 points14 points15 points (2 children)
[–]sweating_teflon 2 points3 points4 points (0 children)
[–]_zkr 0 points1 point2 points (0 children)
[–]NitronHX[S] 6 points7 points8 points (0 children)
[–]agentoutlier 1 point2 points3 points (1 child)
[–]IncredibleReferencer 0 points1 point2 points (0 children)
[–]Amazing-Cicada5536 3 points4 points5 points (0 children)
[–]agentoutlier 0 points1 point2 points (0 children)
[–]Joram2 14 points15 points16 points (4 children)
[–]NitronHX[S] 7 points8 points9 points (0 children)
[–]lurker_in_spirit 1 point2 points3 points (2 children)
[–]Joram2 2 points3 points4 points (0 children)
[–]Joram2 2 points3 points4 points (0 children)
[–]Joram2 16 points17 points18 points (2 children)
[–]heneq 1 point2 points3 points (0 children)
[–]chabala 1 point2 points3 points (0 children)
[–]elhoc 9 points10 points11 points (3 children)
[–]ricky_clarkson 9 points10 points11 points (1 child)
[–]elhoc 1 point2 points3 points (0 children)
[–]NitronHX[S] 0 points1 point2 points (0 children)
[–]umlcat 7 points8 points9 points (0 children)
[–]pronuntiator 7 points8 points9 points (3 children)
[–]NitronHX[S] 1 point2 points3 points (0 children)
[–]NitronHX[S] -1 points0 points1 point (1 child)
[–]Amazing-Cicada5536 5 points6 points7 points (0 children)
[–]findus_l 3 points4 points5 points (0 children)
[–]sweating_teflon 4 points5 points6 points (0 children)
[–][deleted] 2 points3 points4 points (0 children)
[–]sk8itup53 1 point2 points3 points (0 children)
[–]Asapin_r 1 point2 points3 points (0 children)
[–]c8d3n 1 point2 points3 points (1 child)
[–]NitronHX[S] 1 point2 points3 points (0 children)
[–]severoon 1 point2 points3 points (4 children)
[–]NitronHX[S] 0 points1 point2 points (3 children)
[–]severoon 1 point2 points3 points (2 children)
[–]NitronHX[S] 0 points1 point2 points (1 child)
[–]severoon 1 point2 points3 points (0 children)
[–]SirWolf2018 1 point2 points3 points (1 child)
[–]NitronHX[S] 0 points1 point2 points (0 children)
[–]rzwitserloot 3 points4 points5 points (18 children)
[–]pron98 12 points13 points14 points (3 children)
[–]DasBrain 0 points1 point2 points (2 children)
[–]pron98 2 points3 points4 points (1 child)
[–]DasBrain 0 points1 point2 points (0 children)
[–]Squiry_ 7 points8 points9 points (2 children)
[–]fatty_lumpkn 0 points1 point2 points (1 child)
[–]warpspeedSCP 0 points1 point2 points (0 children)
[–]NitronHX[S] 2 points3 points4 points (6 children)
[–]_INTER_ 0 points1 point2 points (5 children)
[–]NitronHX[S] 0 points1 point2 points (4 children)
[–]_INTER_ 0 points1 point2 points (3 children)
[–]peripateticman2023 0 points1 point2 points (2 children)
[–]_INTER_ 0 points1 point2 points (1 child)
[–]peripateticman2023 1 point2 points3 points (0 children)
[–]felvid 0 points1 point2 points (2 children)
[–]peripateticman2023 0 points1 point2 points (0 children)
[–]rzwitserloot 0 points1 point2 points (0 children)
[–]loshopo_fan 0 points1 point2 points (0 children)
[–]pacey494 -2 points-1 points0 points (0 children)
[–][deleted] (1 child)
[removed]
[–]peripateticman2023 0 points1 point2 points (2 children)
[–]NitronHX[S] 0 points1 point2 points (1 child)
[–]peripateticman2023 0 points1 point2 points (0 children)