You are not wrong about cancelabel futures, though.
You are not wrong about cancelabel futures, though.
public sealed interface Maybe<T> {
<T2> Maybe<T2> map(Function<T, T2> mapper);
<T2> Maybe<T2> flatMap(Function<T, Maybe<T2>> mapper);
T elseGet(T fallback);
record Just<T>(T value) implements Maybe<T> {
public <T2> Maybe<T2> map(Function<T, T2> mapper) {
return new Just<T2>(mapper.apply(value));
}
public <T2> Maybe<T2> flatMap(Function<T, Maybe<T2>> mapper) {
return mapper.apply(value);
}
public T elseGet(T fallback) {
return value;
}
}
record Empty<T>() implements Maybe<T> {
public <T2> Maybe<T2> map(Function<T, T2> mapper) {
return new Empty<>();
}
public <T2> Maybe<T2> flatMap(Function<T, Maybe<T2>> mapper) {
return new Empty<>();
}
public T elseGet(T fallback) {
return fallback;
}
}
}
public void demo() {
Maybe<String> foo = new Maybe.Empty<String>();
System.out.println(
switch (foo) {
case Maybe.Just(String val) -> "Hello " + val;
case Maybe.Empty() -> "Fine, leave me hanging";
}
);
}; Maybe<String> foo = null;
foo.map(s -> "bar");
explicit pattern matching is usually discouraged anyway though, and you can do this now with Optional Optional<String> foo = Optional.empty();
String message = foo.map(s -> "Hello " + s).orElse("Fine, leave me hanging");
Other languages like Scala also have an Option.fold method for this specific case.The way Pattern matching works right now is just the beginning.
The best you will get is a warning and the JVM will deoptimize Optional back to a regular object, because somewhere someone set an Optional to null somewhere in a library. It doesn't even have to be as obvious as Optional<String> o = null;
Any cast to Optional can let a null pointer slip from an Object reference. List<Optional<String>> is allowed to contain null pointers and you are allowed to assign o = list.get(0) which generates an implicit cast.
There is no good solution for this. Due to the way generics are implemented.
However, unlike the binary choice of class/value type, project valhalla will provide a more granular approach, coming with incremental performance benefits and constraints.
In the current spec draft, the type system boils down to 4 categories:
- Fully mutable, polymorph classes
- Immutable, monomorphic classes
- Immutable, monomorphic classes + null-hostile
- Immutable, monomorphic classes + null-hostile + multithreading-unsafe
Another story for nullability is being investigated as well which would allow for full performance gain as well as full backwards compatibility.