Skip to content
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

feat(core): Add SolveHandler flatmap #223

Merged
merged 1 commit into from
Dec 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 31 additions & 7 deletions src/main/java/io/github/joselion/maybe/SolveHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -341,13 +341,14 @@ public <X extends Throwable> EffectHandler<X> runEffect(// NOSONAR
}

/**
* If the value is present, map it to another value through the {@code mapper}
* function. If the error is present, the {@code mapper} is never applied and
* the next handler will still contain the error.
*
* @param <U> the type the value will be mapped to
* @param mapper a function that receives the solved value and produces another
* @return a new handler with either the mapped value, or the previous error
* If the value is present, map it to another value using the {@code mapper}
* function. If an error is present, the {@code mapper} function is never
* applied and the next handler will still contain the error.
*
* @param <U> the type the value is mapped to
* @param mapper a function which takes the value as argument and returns
* another value
* @return a new handler with either the mapped value or an error
*/
public <U> SolveHandler<U, E> map(final Function<? super T, ? extends U> mapper) {
return this.value
Expand All @@ -358,6 +359,29 @@ public <U> SolveHandler<U, E> map(final Function<? super T, ? extends U> mapper)
);
}

/**
* If the value is present, map it to another value using the {@code mapper}
* function. If an error is present, the {@code mapper} function is never
* applied and the next handler will still contain the error.
*
* This method is similar to {@link #map(Function)}, but the mapping function is
* one whose result is a {@code Maybe}, and if invoked, flatMap does not wrap
* it within an additional {@code Maybe}.
*
* @param <U> the type the value is mapped to
* @param mapper a function which takes the value as argument and returns a
* {@code Maybe<U>} with another value
* @return a new handler with either the mapped value or an error
*/
public <U> SolveHandler<U, E> flatMap(final Function<? super T, Maybe<? extends U>> mapper) {
return this.value
.mapRight(mapper)
.unwrap(
SolveHandler::failure,
maybe -> maybe.solve(ThrowingFunction.identity())
);
}

/**
* If the value is present, cast the value to anoter type. If the cast fails
* or if the error is present, it returns a new handler which contains a
Expand Down
22 changes: 22 additions & 0 deletions src/test/java/io/github/joselion/maybe/SolveHandlerTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,28 @@
}
}

@Nested class flatMap {
@Nested class when_the_value_is_present {
@Test void returns_a_handler_applying_the_mapper_function() {
final var handler = SolveHandler.from("Hello world!")
.flatMap(x -> Maybe.of(x.length()));

assertThat(handler.success()).contains(12);
assertThat(handler.error()).isEmpty();
}
}

@Nested class when_the_error_is_present {
@Test void returns_a_handler_with_the_previous_error() {
final var handler = SolveHandler.failure(FAIL_EXCEPTION)
.flatMap(x -> Maybe.of(x.toString()));

assertThat(handler.success()).isEmpty();
assertThat(handler.error()).contains(FAIL_EXCEPTION);
}
}
}

@Nested class cast {
@Nested class when_the_value_is_present {
@Nested class and_the_object_can_be_cast {
Expand Down