-
-
Notifications
You must be signed in to change notification settings - Fork 639
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Match.run(cases) syntax #1216
Comments
We suggested in #1218 to drop run(Runnable) in favor of: static <T> Function<T, Void> run(Consumer<? super T> consumer) {
return t -> {
consumer.accept(t);
return null;
};
}
static <T1, T2> BiFunction<T1, T2, Void> run(BiConsumer<? super T1, ? super T2> consumer) {
return (t1, t2) -> {
consumer.accept(t1, t2);
return null;
};
}
void test() {
Match(new Object()).of(
Case(instanceOf(Integer.class), run(i -> System.out.println(i))),
Case(instanceOf(Double.class), run(d -> System.out.println(d))),
Case($(), run(ignored -> { throw new NumberFormatException(); }))
);
} This needs to be tested for all Consumers to ensure that there are no ambiguities. Where to place the Consumers? As top-level interfaces in package |
This is not a bug, the run() method has to be used in another way. We must not use // R Case(Pattern0<T>, R)
Case($(o -> false), run(...)) In the above example // R Case(Pattern0<T>, Function<T, R>)
Case($(o -> false), o -> run(...)) In the above example Because we cannot provide a How can the Match API evolve in the way that we are able to run code in a Match Case (in a concise way) while staying safe? We need an API that makes clear that side-effects take place, i.e. that no value is returned. This can be accomplished by adding Match(obj).run(cases) where we have to ensure that only cases are used that result in Runnables. I think of Match(obj).run(
Case(Pattern, () -> ...) // Runnable as return value
Case(Pattern, (t1, ..., tn) -> () -> {}) // curried form of a Runnable as function
) I need to check if this or s.th. similar is posstible. |
This works well, run is not evaluated eagerly: @Test
public void shouldRunUnitOfWork() {
class OuterWorld {
String effect = null;
void displayHelp() {
effect = "help";
}
void displayVersion() {
effect = "version";
}
}
final OuterWorld outerWorld = new OuterWorld();
Match("-v").of(
Case(isIn("-h", "--help"), o -> run(outerWorld::displayHelp)),
Case(isIn("-v", "--version"), o -> run(outerWorld::displayVersion)),
Case($(), o -> { throw new IllegalArgumentException(); })
);
assertThat(outerWorld.effect).isEqualTo("version");
}
@Test
public void shouldRunWithInferredArguments() {
class OuterWorld {
Number effect = null;
void writeInt(int i) {
effect = i;
}
void writeDouble(double d) {
effect = d;
}
}
final OuterWorld outerWorld = new OuterWorld();
final Object obj = .1d;
Match(obj).of(
Case(instanceOf(Integer.class), i -> run(() -> outerWorld.writeInt(i))),
Case(instanceOf(Double.class), d -> run(() -> outerWorld.writeDouble(d))),
Case($(), o -> { throw new NumberFormatException(); })
);
assertThat(outerWorld.effect).isEqualTo(.1d);
} |
We will not push side-effecting programming. |
Timo Nentwig figured out that the following Match example (from the blog post Pattern Matching Essentials) does not work:
All cases are evaluated eagerly, the last throws and the of() method is never reached.
Reason/Bug: the API.run(Runnable) method evaluates eagerly.
I'm not sure how to process further:
Solution 1) remove the run() method
Solution 2) lift the Runnable to a return value in order to fit Case(..., R):
The text was updated successfully, but these errors were encountered: