Ich weiß, dass das schöner aussieht, aber ich bin mit sowas schon in Probleme gerannt. Was ist, wenn wirklich jemand einen Either<Supplier<String>,Supplier<Integer>>
haben will?
zu 5. Nice to have
Mir ist gerade auf der Hollywoodschaukel ein lustiger Gedanke gekommen, den ich für **sehr **„nice to have“ halte - allerding muss ich erst noch sehen, ob das wirklich so geht, wie ich mir das vorstelle. Wie wäre ein DSL ähnlich Scalas match
? Das wäre auf jeden Fall praktisch für Either, Tuples, Optional und Listen, eventuell für mehr. Ich stelle mir das so vor:
Optional<Integer> opt = ...
String s = match(opt).cases(
none(() -> "leer"),
some(42, () -> "die Antwort!"),
some(a -> "gerade").when(a -> a % 2 == 0),
defaultValue(x -> "nix gefunden: " + x.toString())
);
Das wäre auch etwas, das ich in anderen Frameworks noch nicht gesehen habe, und es passt sehr gut zu unserem „Kerngebiet“.
Ich teste das mal…
*** Edit ***
Ja, es funktioniert mit einigen Änderungen so. Hier der Code, der Optional
abdeckt:
import java.util.Optional;
public interface Case<T,R> {
Optional<R> accept(T value);
}
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;
import static java.util.Optional.of;
public final class Matcher {
private Matcher() {}
@SafeVarargs
public static <T,R> R match(T value, Case<T,R> ... cases) throws MatchException {
for(Case<T,R> c : cases) {
Optional<R> result = c.accept(value);
if (result.isPresent()) {
return result.get();
}
}
throw new MatchException();
}
public static <T,R> Case<T,R> Default(Supplier<R> supplier) {
return value -> of(supplier.get());
}
public static <T,R> Case<T,R> Default(Function<T, R> fn) {
return value -> of(fn.apply(value));
}
}
public class MatchException extends RuntimeException {
public MatchException() {}
public MatchException(String message) {
super(message);
}
public MatchException(String message, Throwable cause) {
super(message, cause);
}
public MatchException(Throwable cause) {
super(cause);
}
}
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import static java.util.Optional.of;
public final class OptionalCases {
private OptionalCases(){}
public static <T,R> Case<Optional<T>,R> None(Supplier<R> supplier) {
return t -> t.isPresent()
? Optional.<R>empty()
: of(supplier.get());
}
public static <T,R> Case<Optional<T>,R> Some(T value, Supplier<R> supplier) {
return t -> t.isPresent() && t.get().equals(value)
? of(supplier.get())
: Optional.<R>empty();
}
public static <T,R> Case<Optional<T>,R> some(Function<T,R> fn) {
return t -> t.isPresent()
? of(fn.apply(t.get()))
: Optional.<R>empty();
}
public static <T,R> Case<Optional<T>,R> SomeIf(Function<T, R> fn, Predicate<T> predicate) {
return t -> t.isPresent() && predicate.test(t.get())
? of(fn.apply(t.get()))
: Optional.<R>empty();
}
}
import java.util.Optional;
import static net.neco.core.matcher.Matcher.*;
import static net.neco.core.matcher.OptionalCases.*;
public class Test {
public static void main(String[] args) {
test(Optional.empty());
test(Optional.of(42));
test(Optional.of(12));
test(Optional.of(13));
}
private static void test(Optional<Integer> opt) {
String s = match(opt,
None(() -> "leer"),
Some(42, () -> "die Antwort!"),
SomeIf(a -> "gerade", a -> a % 2 == 0),
Default(x -> "nix gefunden: " + x.toString())
);
System.out.println(s);
}
}
Sorry für die Großschreibung, so sieht es aber fast wie Scala aus
*** Edit ***
Ich habe mal auf bitbucket.org ein 5-Mann-Projekt neco4j (ID neco4j angelegt). PW per PN.