diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index caeee074e..5f9d31c2d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -193,7 +193,7 @@ Note: Detailed information about performing a release can be found in the SCM se ### Branching Model -We following a simple git workflow/branching model: +We follow a simple git workflow/branching model: ``` master diff --git a/vavr/src/main/java/io/vavr/CheckedConsumer.java b/vavr/src/main/java/io/vavr/CheckedConsumer.java index fc43db2e1..5a7bdcdf8 100644 --- a/vavr/src/main/java/io/vavr/CheckedConsumer.java +++ b/vavr/src/main/java/io/vavr/CheckedConsumer.java @@ -24,30 +24,31 @@ import static io.vavr.CheckedConsumerModule.sneakyThrow; /** - * A consumer that may throw, equivalent to {@linkplain java.util.function.Consumer}. + * A {@linkplain java.util.function.Consumer} that is allowed to throw checked exceptions. * - * @param the value type supplied to this consumer. + * @param the type of the input to the consumer */ @FunctionalInterface public interface CheckedConsumer { /** - * Creates a {@code CheckedConsumer}. + * Creates a {@code CheckedConsumer} from the given method reference or lambda. * + *

Example usage:

*
{@code
      * final CheckedConsumer checkedConsumer = CheckedConsumer.of(Value::stdout);
      * final Consumer consumer = checkedConsumer.unchecked();
      *
-     * // prints "Hi" on the console
+     * // prints "Hi" to the console
      * consumer.accept(CharSeq.of("Hi!"));
      *
-     * // throws
+     * // may throw an exception
      * consumer.accept(null);
      * }
* - * @param methodReference (typically) a method reference, e.g. {@code Type::method} - * @param type of values that are accepted by the consumer - * @return a new {@code CheckedConsumer} + * @param methodReference typically a method reference, e.g. {@code Type::method} + * @param the type of values accepted by the consumer + * @return a new {@code CheckedConsumer} wrapping the given method reference * @see CheckedFunction1#of(CheckedFunction1) */ static CheckedConsumer of(CheckedConsumer methodReference) { @@ -55,18 +56,18 @@ static CheckedConsumer of(CheckedConsumer methodReference) { } /** - * Performs side-effects. + * Performs an action on the given value, potentially causing side-effects. * - * @param t a value of type {@code T} - * @throws Throwable if an error occurs + * @param t the input value of type {@code T} + * @throws Throwable if an error occurs during execution */ void accept(T t) throws Throwable; /** - * Returns a chained {@code CheckedConsumer} that first executes {@code this.accept(t)} - * and then {@code after.accept(t)}, for a given {@code t} of type {@code T}. + * Returns a composed {@code CheckedConsumer} that performs, in sequence, + * {@code this.accept(t)} followed by {@code after.accept(t)} for the same input {@code t}. * - * @param after the action that will be executed after this action + * @param after the action to execute after this action * @return a new {@code CheckedConsumer} that chains {@code this} and {@code after} * @throws NullPointerException if {@code after} is null */ @@ -76,9 +77,10 @@ default CheckedConsumer andThen(CheckedConsumer after) { } /** - * Returns an unchecked {@link Consumer} that will sneaky throw if an exceptions occurs when accepting a value. + * Returns an unchecked {@link Consumer} that sneakily throws any exception + * encountered while accepting a value. * - * @return a new {@link Consumer} that throws a {@code Throwable}. + * @return a {@link Consumer} that may throw any {@link Throwable} without declaring it */ default Consumer unchecked() { return t -> { diff --git a/vavr/src/main/java/io/vavr/CheckedPredicate.java b/vavr/src/main/java/io/vavr/CheckedPredicate.java index f2f9633b1..88d17e793 100644 --- a/vavr/src/main/java/io/vavr/CheckedPredicate.java +++ b/vavr/src/main/java/io/vavr/CheckedPredicate.java @@ -23,7 +23,7 @@ import static io.vavr.CheckedPredicateModule.sneakyThrow; /** - * A {@linkplain java.util.function.Predicate} which may throw. + * A {@linkplain java.util.function.Predicate} that is allowed to throw checked exceptions. * * @param the type of the input to the predicate */ @@ -31,22 +31,23 @@ public interface CheckedPredicate { /** - * Creates a {@code CheckedPredicate}. + * Creates a {@code CheckedPredicate} from the given method reference or lambda. * + *

Example usage:

*
{@code
      * final CheckedPredicate checkedPredicate = CheckedPredicate.of(Boolean::booleanValue);
      * final Predicate predicate = checkedPredicate.unchecked();
      *
-     * // = true
+     * // returns true
      * predicate.test(Boolean.TRUE);
      *
-     * // throws
+     * // may throw an exception
      * predicate.test(null);
      * }
* - * @param methodReference (typically) a method reference, e.g. {@code Type::method} - * @param type of values that are tested by the predicate - * @return a new {@code CheckedPredicate} + * @param methodReference typically a method reference, e.g. {@code Type::method} + * @param the type of values tested by the predicate + * @return a new {@code CheckedPredicate} wrapping the given method reference * @see CheckedFunction1#of(CheckedFunction1) */ static CheckedPredicate of(CheckedPredicate methodReference) { @@ -57,24 +58,25 @@ static CheckedPredicate of(CheckedPredicate methodReference) { * Evaluates this predicate on the given argument. * * @param t the input argument - * @return {@code true} if the input argument matches the predicate, otherwise {@code false} - * @throws Throwable if an error occurs + * @return {@code true} if the argument satisfies the predicate, {@code false} otherwise + * @throws Throwable if an error occurs during evaluation */ boolean test(T t) throws Throwable; /** - * Negates this predicate. + * Returns a predicate that represents the logical negation of this predicate. * - * @return A new CheckedPredicate. + * @return a new {@code CheckedPredicate} representing the negated condition */ default CheckedPredicate negate() { return t -> !test(t); } /** - * Returns an unchecked {@link Predicate} that will sneaky throw if an exceptions occurs when testing a value. + * Returns an unchecked {@link Predicate} that sneakily throws any exception + * encountered when testing a value. * - * @return a new {@link Predicate} that throws a {@code Throwable}. + * @return a {@link Predicate} that may throw any {@link Throwable} without declaring it */ default Predicate unchecked() { return t -> { diff --git a/vavr/src/main/java/io/vavr/CheckedRunnable.java b/vavr/src/main/java/io/vavr/CheckedRunnable.java index 41715f3bf..f197d1671 100644 --- a/vavr/src/main/java/io/vavr/CheckedRunnable.java +++ b/vavr/src/main/java/io/vavr/CheckedRunnable.java @@ -21,28 +21,29 @@ import static io.vavr.CheckedRunnableModule.sneakyThrow; /** - * A {@linkplain Runnable} which may throw. + * A {@linkplain Runnable} that is allowed to throw checked exceptions. */ @FunctionalInterface public interface CheckedRunnable { /** - * Creates a {@code CheckedRunnable}. + * Creates a {@code CheckedRunnable} from the given method reference or lambda. * + *

Example usage:

*
{@code
      * // class Evil { static void sideEffect() { ... } }
      * final CheckedRunnable checkedRunnable = CheckedRunnable.of(Evil::sideEffect);
      * final Runnable runnable = checkedRunnable.unchecked();
      *
-     * // may or may not perform a side-effect while not throwing
+     * // may or may not perform the side-effect without throwing checked exceptions
      * runnable.run();
      *
-     * // may or may not perform a side-effect while throwing
+     * // may or may not perform the side-effect while potentially throwing
      * runnable.run();
      * }
* - * @param methodReference (typically) a method reference, e.g. {@code Type::method} - * @return a new {@code CheckedRunnable} + * @param methodReference typically a method reference, e.g. {@code Type::method} + * @return a new {@code CheckedRunnable} wrapping the given method reference * @see CheckedFunction1#of(CheckedFunction1) */ static CheckedRunnable of(CheckedRunnable methodReference) { @@ -50,16 +51,18 @@ static CheckedRunnable of(CheckedRunnable methodReference) { } /** - * Performs side-effects. + * Executes the action, potentially performing side-effects. * - * @throws Throwable if an error occurs + * @throws Throwable if an error occurs during execution */ + void run() throws Throwable; /** - * Returns an unchecked {@link Runnable} that will sneaky throw if an exceptions occurs when running the unit of work. + * Returns an unchecked {@link Runnable} that sneakily throws any exception + * encountered during execution of this unit of work. * - * @return a new {@link Runnable} that throws a {@code Throwable}. + * @return a {@link Runnable} that may throw any {@link Throwable} without declaring it */ default Runnable unchecked() { return () -> { diff --git a/vavr/src/main/java/io/vavr/Lazy.java b/vavr/src/main/java/io/vavr/Lazy.java index 4f15373cc..b2ee2051b 100644 --- a/vavr/src/main/java/io/vavr/Lazy.java +++ b/vavr/src/main/java/io/vavr/Lazy.java @@ -35,28 +35,29 @@ import java.util.function.Supplier; /** - * Represents a lazy evaluated value. Compared to a Supplier, Lazy is memoizing, i.e. it evaluates only once and - * therefore is referential transparent. + * Represents a lazily evaluated value. Unlike a standard {@link java.util.function.Supplier}, + * {@code Lazy} is memoizing: the computation is performed at most once, ensuring referential transparency. * - *
- * 
+ * 

This type behaves more like a Functor than a Monad: it represents a value rather than capturing + * a specific state. Therefore, it does not provide operations like {@code flatMap} or {@code orElse}.

+ * + *

Example usage:

+ *

  * final Lazy<Double> l = Lazy.of(Math::random);
- * l.isEvaluated(); // = false
- * l.get();         // = 0.123 (random generated)
- * l.isEvaluated(); // = true
- * l.get();         // = 0.123 (memoized)
- * 
- * 
+ * l.isEvaluated(); // false + * double value = l.get(); // evaluates and returns a random number, e.g., 0.123 + * l.isEvaluated(); // true + * double memoizedValue = l.get(); // returns the same value as before, e.g., 0.123 + *
* - * Example of creating a real lazy value (works only with interfaces): + *

Creating a truly lazy value for an interface type:

+ *

+ * final CharSequence chars = Lazy.val(() -> "Yay!", CharSequence.class);
+ * 
* - *
final CharSequence chars = Lazy.val(() -> "Yay!", CharSequence.class);
- * - * @param The type of the lazy evaluated value + * @param the type of the lazily evaluated value * @author Daniel Dietrich */ -// DEV-NOTE: No flatMap and orElse because this more like a Functor than a Monad. -// It represents a value rather than capturing a specific state. public final class Lazy implements Value, Supplier, Serializable { private static final long serialVersionUID = 1L; @@ -74,13 +75,12 @@ private Lazy(Supplier supplier) { } /** - * Narrows a widened {@code Lazy} to {@code Lazy} - * by performing a type-safe cast. This is eligible because immutable/read-only - * collections are covariant. + * Narrows a {@code Lazy} to {@code Lazy} via a type-safe cast. + * This is safe because immutable or read-only collections are covariant. * - * @param lazy A {@code Lazy}. - * @param Component type of the {@code Lazy}. - * @return the given {@code lazy} instance as narrowed type {@code Lazy}. + * @param lazy the {@code Lazy} instance to narrow + * @param the type of the value + * @return the given {@code lazy} instance as a {@code Lazy} */ @SuppressWarnings("unchecked") public static Lazy narrow(Lazy lazy) { @@ -88,12 +88,12 @@ public static Lazy narrow(Lazy lazy) { } /** - * Creates a {@code Lazy} that requests its value from a given {@code Supplier}. The supplier is asked only once, - * the value is memoized. + * Creates a {@code Lazy} instance that obtains its value from the given {@code Supplier}. + * The supplier is invoked at most once, and the result is cached for subsequent calls. * - * @param type of the lazy value - * @param supplier A supplier - * @return A new instance of Lazy + * @param the type of the lazy value + * @param supplier the supplier providing the value + * @return a new {@code Lazy} instance */ @SuppressWarnings("unchecked") public static Lazy of(Supplier supplier) { @@ -106,13 +106,15 @@ public static Lazy of(Supplier supplier) { } /** - * Reduces many {@code Lazy} values into a single {@code Lazy} by transforming an - * {@code Iterable>} into a {@code Lazy>}. + * Combines multiple {@code Lazy} instances into a single {@code Lazy} containing a sequence of their evaluated values. + * + *

Transforms an {@code Iterable>} into a {@code Lazy>}, evaluating each value lazily + * when the resulting {@code Lazy} is accessed.

* - * @param Type of the lazy values. - * @param values An iterable of lazy values. - * @return A lazy sequence of values. - * @throws NullPointerException if values is null + * @param the type of the lazy values + * @param values an {@code Iterable} of lazy values + * @return a {@code Lazy} containing a sequence of the evaluated values + * @throws NullPointerException if {@code values} is null */ @SuppressWarnings("Convert2MethodRef") // TODO should be fixed in JDK 9 and Idea public static Lazy> sequence(Iterable> values) { @@ -121,13 +123,13 @@ public static Lazy> sequence(Iterable> va } /** - * Creates a real _lazy value_ of type {@code T}, backed by a {@linkplain java.lang.reflect.Proxy} which delegates - * to a {@code Lazy} instance. + * Creates a true lazy value of type {@code T}, implemented using a {@linkplain java.lang.reflect.Proxy} + * that delegates to a {@code Lazy} instance. * - * @param supplier A supplier - * @param type An interface - * @param type of the lazy value - * @return A new instance of T + * @param supplier the supplier providing the value when needed + * @param type the interface class that the proxy should implement + * @param the type of the lazy value + * @return a new proxy instance of type {@code T} that evaluates lazily */ @GwtIncompatible("reflection is not supported") @SuppressWarnings("unchecked") @@ -148,10 +150,10 @@ public Option filter(Predicate predicate) { } /** - * Evaluates this lazy value and caches it, when called the first time. - * On subsequent calls, returns the cached value. + * Evaluates this lazy value on the first call and caches the result. + * Subsequent calls return the cached value without recomputation. * - * @return the lazy evaluated value + * @return the evaluated value */ @Override public T get() { @@ -173,9 +175,9 @@ private T computeValue() { } /** - * A {@code Lazy}'s value is computed synchronously. + * Indicates that this {@code Lazy} value is computed synchronously. * - * @return false + * @return {@code false} */ @Override public boolean isAsync() { @@ -188,21 +190,21 @@ public boolean isEmpty() { } /** - * Checks, if this lazy value is evaluated. - *

- * Note: A value is internally evaluated (once) by calling {@link #get()}. + * Checks whether this lazy value has been evaluated. + * + *

Note: The value is evaluated internally (at most once) when {@link #get()} is called.

* - * @return true, if the value is evaluated, false otherwise. - * @throws UnsupportedOperationException if this value is undefined + * @return {@code true} if the value has been evaluated, {@code false} otherwise + * @throws UnsupportedOperationException if this lazy value is undefined */ public boolean isEvaluated() { return supplier == null; } /** - * A {@code Lazy}'s value is computed lazily. + * Indicates that this {@code Lazy} value is computed lazily. * - * @return true + * @return {@code true} */ @Override public boolean isLazy() { @@ -241,11 +243,12 @@ public Lazy peek(Consumer action) { } /** - * Transforms this {@code Lazy}. + * Applies a transformation function to the value contained in this {@code Lazy}, producing a new {@code Lazy} instance + * of the transformed value. * - * @param f A transformation - * @param Type of transformation result - * @return An instance of type {@code U} + * @param f the function to transform the value + * @param the type of the result of the transformation + * @return a new {@code Lazy} instance containing the transformed value * @throws NullPointerException if {@code f} is null */ public U transform(Function, ? extends U> f) { @@ -274,10 +277,10 @@ public String toString() { } /** - * Ensures that the value is evaluated before serialization. + * Forces the lazy value to be evaluated before it is serialized. * - * @param s An object serialization stream. - * @throws java.io.IOException If an error occurs writing to the stream. + * @param s the object output stream to write to + * @throws java.io.IOException if an I/O error occurs during serialization */ @GwtIncompatible("The Java serialization protocol is explicitly not supported") private void writeObject(ObjectOutputStream s) throws IOException { diff --git a/vavr/src/main/java/io/vavr/Memoized.java b/vavr/src/main/java/io/vavr/Memoized.java index 160c074ff..24cd5db7b 100644 --- a/vavr/src/main/java/io/vavr/Memoized.java +++ b/vavr/src/main/java/io/vavr/Memoized.java @@ -1,7 +1,4 @@ package io.vavr; -/** - * INTERNAL. Zero abstract method (ZAM) / tagging interface. - */ interface Memoized { } diff --git a/vavr/src/main/java/io/vavr/PartialFunction.java b/vavr/src/main/java/io/vavr/PartialFunction.java index 899eb448f..80c33e456 100644 --- a/vavr/src/main/java/io/vavr/PartialFunction.java +++ b/vavr/src/main/java/io/vavr/PartialFunction.java @@ -22,18 +22,19 @@ import java.util.function.Function; /** - * Represents a partial function T -> R that is not necessarily defined for all input values of type T. - * The caller is responsible for calling the method isDefinedAt() before this function is applied to the value. - *

- * If the function is not defined for a specific value, apply() may produce an arbitrary result. - * More specifically it is not guaranteed that the function will throw an exception. - *

- * If the function is defined for a specific value, apply() may still throw an exception. + * Represents a partial function {@code T -> R} that may not be defined for all input values of type {@code T}. + * The caller is responsible for checking {@link #isDefinedAt(Object)} before applying this function. * - * @param type of the function input, called domain of the function - * @param type of the function output, called codomain of the function + *

If the function is not defined for a given value, {@link #apply(Object)} may produce an arbitrary result. + * There is no guarantee that an exception will be thrown in this case.

+ * + *

If the function is defined for a given value, {@link #apply(Object)} may still throw an exception during execution.

+ * + * @param the type of the function input (the domain) + * @param the type of the function output (the codomain) * @author Daniel Dietrich */ + public interface PartialFunction extends Function1 { /** @@ -42,14 +43,16 @@ public interface PartialFunction extends Function1 { long serialVersionUID = 1L; /** - * Unlifts a {@code totalFunction} that returns an {@code Option} result into a partial function. - * The total function should be side effect free because it might be invoked twice: when checking if the - * unlifted partial function is defined at a value and when applying the partial function to a value. + * Converts (or "unlifts") a {@code totalFunction} that returns an {@code Option} into a partial function. + *

+ * The provided {@code totalFunction} should be side-effect-free, because it may be invoked twice: + * once when checking if the resulting partial function is defined at a value, and once when applying + * the partial function to that value. * - * @param totalFunction the function returning an {@code Option} result. - * @param type of the function input, called domain of the function - * @param type of the function output, called codomain of the function - * @return a partial function that is not necessarily defined for all input values of type T. + * @param totalFunction the function returning an {@code Option} result + * @param the type of the function input (the domain) + * @param the type of the function output (the codomain) + * @return a partial function that is defined only for inputs for which the {@code totalFunction} returns a defined {@code Option} */ static PartialFunction unlift(Function> totalFunction) { return new PartialFunction() { @@ -70,14 +73,14 @@ public boolean isDefinedAt(T value) { } /** - * Factory method for creating a partial function that maps a given {@code Value} to its underlying value. - * The partial function is defined for an input {@code Value} if and only if the input {@code Value} is not - * empty. If the input {@code Value} is not empty, the partial function will return the underlying value of - * the input {@code Value}. + * Creates a partial function that maps a given {@code Value} to its underlying value. + *

+ * The resulting partial function is defined for an input {@code Value} if and only if the {@code Value} is not empty. + * For defined inputs, the partial function returns the underlying value contained in the {@code Value}. * - * @param type of the underlying value of the input {@code Value}. - * @param type of the function input, called domain of the function - * @return a partial function that maps a {@code Value} to its underlying value. + * @param the type of the underlying value + * @param the type of the input {@code Value} (the domain of the function) + * @return a partial function that maps a non-empty {@code Value} to its underlying value */ static > PartialFunction getIfDefined() { return new PartialFunction() { @@ -100,25 +103,26 @@ public boolean isDefinedAt(V v) { /** * Applies this function to the given argument and returns the result. * - * @param t the argument - * @return the result of function application - * + * @param t the input argument + * @return the result of applying this function to the input */ R apply(T t); /** - * Tests if a value is contained in the function's domain. + * Tests whether a value is contained in the function's domain. * - * @param value a potential function argument - * @return true, if the given value is contained in the function's domain, false otherwise + * @param value a potential input to the function + * @return {@code true} if the given value is contained in the function's domain, {@code false} otherwise */ boolean isDefinedAt(T value); /** * Lifts this partial function into a total function that returns an {@code Option} result. * - * @return a function that applies arguments to this function and returns {@code Some(result)} - * if the function is defined for the given arguments, and {@code None} otherwise. + *

The resulting function applies an argument to this partial function and returns + * {@code Some(result)} if the function is defined for that argument, or {@code None} if it is not defined.

+ * + * @return a total function that returns an {@code Option} containing the result if defined, or {@code None} otherwise */ default Function1> lift() { return t -> Option.when(isDefinedAt(t), () -> apply(t)); diff --git a/vavr/src/main/java/io/vavr/Predicates.java b/vavr/src/main/java/io/vavr/Predicates.java index 486c47cfb..d22bb8f8a 100644 --- a/vavr/src/main/java/io/vavr/Predicates.java +++ b/vavr/src/main/java/io/vavr/Predicates.java @@ -35,24 +35,26 @@ private Predicates() { } /** - * A combinator that checks if all of the given {@code predicates} are satisfied. - *

- * By definition {@code allOf} is satisfied if the given {@code predicates} are empty. + * Returns a predicate that is satisfied only when all of the provided {@code predicates} + * return {@code true} for a given input. + * + *

If no predicates are supplied, the resulting predicate always evaluates to {@code true}.

* *
{@code
      * Predicate isGreaterThanOne = i -> i > 1;
      * Predicate isGreaterThanTwo = i -> i > 2;
+     *
      * allOf().test(0);                                   // true
      * allOf(isGreaterThanOne, isGreaterThanTwo).test(3); // true
      * allOf(isGreaterThanOne, isGreaterThanTwo).test(2); // false
      * }
* - * @param predicates An array of predicates - * @param closure over tested object types - * @return A new {@code Predicate} + * @param predicates the predicates to combine + * @param the input type + * @return a predicate representing the logical conjunction of all given predicates * @throws NullPointerException if {@code predicates} is null */ - @SuppressWarnings({ "unchecked", "varargs" }) + @SuppressWarnings({"varargs" }) @SafeVarargs public static Predicate allOf(Predicate... predicates) { Objects.requireNonNull(predicates, "predicates is null"); @@ -60,23 +62,27 @@ public static Predicate allOf(Predicate... predicates) { } /** - * A combinator that checks if at least one of the given {@code predicates} is satisfies. + * Returns a predicate that is satisfied if at least one of the provided {@code predicates} + * returns {@code true} for a given input. + * + *

If no predicates are supplied, the resulting predicate always evaluates to {@code false}.

* *
{@code
      * Predicate isGreaterThanOne = i -> i > 1;
      * Predicate isGreaterThanTwo = i -> i > 2;
+     *
      * anyOf().test(0);                                   // false
      * anyOf(isGreaterThanOne, isGreaterThanTwo).test(3); // true
      * anyOf(isGreaterThanOne, isGreaterThanTwo).test(2); // true
      * anyOf(isGreaterThanOne, isGreaterThanTwo).test(1); // false
      * }
- * - * @param predicates An array of predicates - * @param closure over tested object types - * @return A new {@code Predicate} + * + * @param predicates the predicates to combine + * @param the input type + * @return a predicate representing the logical disjunction of all given predicates * @throws NullPointerException if {@code predicates} is null */ - @SuppressWarnings({ "unchecked", "varargs" }) + @SuppressWarnings({"varargs" }) @SafeVarargs public static Predicate anyOf(Predicate... predicates) { Objects.requireNonNull(predicates, "predicates is null"); @@ -84,18 +90,23 @@ public static Predicate anyOf(Predicate... predicates) { } /** - * A combinator that checks if one or more elements of an {@code Iterable} satisfy the {@code predicate}. + * Returns a predicate that checks if at least one element in an {@code Iterable} + * satisfies the given {@code predicate}. + * + *

If the {@code Iterable} is empty, the resulting predicate evaluates to {@code false}.

* *
{@code
      * Predicate isGreaterThanOne = i -> i > 1;
      * Predicate> existsGreaterThanOne = exists(isGreaterThanOne);
+     *
      * existsGreaterThanOne.test(List.of(0, 1, 2)); // true
      * existsGreaterThanOne.test(List.of(0, 1));    // false
+     * existsGreaterThanOne.test(Collections.emptyList()); // false
      * }
- * - * @param predicate A {@code Predicate} that tests elements of type {@code T} - * @param tested object type - * @return A new {@code Predicate} + * + * @param predicate the predicate to test elements against + * @param the type of elements in the {@code Iterable} + * @return a predicate that evaluates to {@code true} if any element satisfies {@code predicate} * @throws NullPointerException if {@code predicate} is null */ public static Predicate> exists(Predicate predicate) { @@ -104,18 +115,23 @@ public static Predicate> exists(Predicate predicate) } /** - * A combinator that checks if all elements of an {@code Iterable} satisfy the {@code predicate}. + * Returns a predicate that checks if all elements in an {@code Iterable} + * satisfy the given {@code predicate}. + * + *

If the {@code Iterable} is empty, the resulting predicate evaluates to {@code true}.

* *
{@code
      * Predicate isGreaterThanOne = i -> i > 1;
      * Predicate> forAllGreaterThanOne = forAll(isGreaterThanOne);
+     *
      * forAllGreaterThanOne.test(List.of(0, 1, 2)); // false
      * forAllGreaterThanOne.test(List.of(2, 3, 4)); // true
+     * forAllGreaterThanOne.test(Collections.emptyList()); // true
      * }
* - * @param predicate A {@code Predicate} that tests elements of type {@code T} - * @param tested object type - * @return A new {@code Predicate} + * @param predicate the predicate to test elements against + * @param the type of elements in the {@code Iterable} + * @return a predicate that evaluates to {@code true} only if all elements satisfy {@code predicate} * @throws NullPointerException if {@code predicate} is null */ public static Predicate> forAll(Predicate predicate) { @@ -124,17 +140,18 @@ public static Predicate> forAll(Predicate predicate) } /** - * Creates a {@code Predicate} that tests, if an object is instance of the specified {@code type}. + * Returns a {@code Predicate} that tests whether an object is an instance of the specified {@code type}. * *
{@code
      * Predicate instanceOfNumber = instanceOf(Number.class);
+     *
      * instanceOfNumber.test(1);    // true
      * instanceOfNumber.test("1");  // false
      * }
      *
-     * @param type A type
-     * @param   tested object type
-     * @return A new {@code Predicate}
+     * @param type the class to test instances against
+     * @param  the type of objects being tested
+     * @return a predicate that evaluates to {@code true} if the object is an instance of {@code type}
      * @throws NullPointerException if {@code type} is null
      */
     // DEV-NOTE: We need Class instead of Class, see {@link TryTest#shouldRecoverSuccessUsingCase()}
@@ -145,39 +162,43 @@ public static  Predicate instanceOf(Class type) {
     }
 
     /**
-     * Creates a {@code Predicate} that tests, if an object is equal to the specified {@code value} using
-     * {@link Objects#equals(Object, Object)} for comparison.
+     * Returns a {@code Predicate} that tests whether an object is equal to the specified {@code value},
+     * using {@link Objects#equals(Object, Object)} for comparison.
      *
      * 
{@code
      * Predicate isOne = is(1);
+     *
      * isOne.test(1); // true
      * isOne.test(2); // false
+     * isOne.test(null); // false
      * }
* - * @param value A value, may be null - * @param tested object type - * @return A new {@code Predicate} + * @param value the value to compare against; may be {@code null} + * @param the type of object being tested + * @return a predicate that evaluates to {@code true} if the tested object equals {@code value} */ public static Predicate is(T value) { return obj -> Objects.equals(obj, value); } /** - * Creates a {@code Predicate} that tests, if an object is equal to at least one of the specified {@code values} + * Returns a {@code Predicate} that tests whether an object is equal to at least one of the specified {@code values}, * using {@link Objects#equals(Object, Object)} for comparison. * *
{@code
      * Predicate isIn = isIn(1, 2, 3);
+     *
      * isIn.test(1); // true
      * isIn.test(0); // false
+     * isIn.test(null); // false
      * }
* - * @param values an array of values of type T - * @param closure over tested object types - * @return A new {@code Predicate} + * @param values the values to compare against; may not be {@code null} + * @param the type of objects being tested + * @return a predicate that evaluates to {@code true} if the tested object equals any of the specified {@code values} * @throws NullPointerException if {@code values} is null */ - @SuppressWarnings({ "unchecked", "varargs" }) + @SuppressWarnings({"varargs" }) @SafeVarargs public static Predicate isIn(T... values) { Objects.requireNonNull(values, "values is null"); @@ -185,56 +206,60 @@ public static Predicate isIn(T... values) { } /** - * Creates a {@code Predicate} that tests, if an object is not null + * Returns a {@code Predicate} that tests whether an object is not {@code null}. * *
{@code
      * Predicate isNotNull = isNotNull();
+     *
      * isNotNull.test(0);    // true
      * isNotNull.test(null); // false
      * }
* - * @param tested object type - * @return A new {@code Predicate} + * @param the type of object being tested + * @return a predicate that evaluates to {@code true} if the tested object is not {@code null} */ public static Predicate isNotNull() { return Objects::nonNull; } /** - * Creates a {@code Predicate} that tests, if an object is null + * Returns a {@code Predicate} that tests whether an object is {@code null}. * *
{@code
      * Predicate isNull = isNull();
+     *
      * isNull.test(null); // true
      * isNull.test(0);    // false
      * }
* - * @param tested object type - * @return A new {@code Predicate} + * @param the type of object being tested + * @return a predicate that evaluates to {@code true} if the tested object is {@code null} */ public static Predicate isNull() { return Objects::isNull; } /** - * A combinator that checks if none of the given {@code predicates} is satisfied. - *

- * Naturally {@code noneOf} is satisfied if the given {@code predicates} are empty. + * Returns a predicate that is satisfied if none of the provided {@code predicates} + * return {@code true} for a given input. + * + *

If no predicates are supplied, the resulting predicate always evaluates to {@code true}.

* *
{@code
      * Predicate isGreaterThanOne = i -> i > 1;
      * Predicate isGreaterThanTwo = i -> i > 2;
+     *
      * noneOf().test(0);                                   // true
      * noneOf(isGreaterThanOne, isGreaterThanTwo).test(1); // true
      * noneOf(isGreaterThanOne, isGreaterThanTwo).test(2); // false
      * }
* - * @param predicates An array of predicates - * @param closure over tested object types - * @return A new {@code Predicate} + * @param predicates the predicates to combine + * @param the input type + * @return a predicate that evaluates to {@code true} only if all predicates return {@code false} * @throws NullPointerException if {@code predicates} is null */ - @SuppressWarnings({ "unchecked", "varargs" }) + @SuppressWarnings({"varargs" }) @SafeVarargs public static Predicate noneOf(Predicate... predicates) { Objects.requireNonNull(predicates, "predicates is null"); @@ -242,23 +267,23 @@ public static Predicate noneOf(Predicate... predicates) { } /** - * Negates a given {@code Predicate}. + * Returns a predicate that negates the result of the given {@code predicate}. * *
{@code
-     * // negates a method reference
+     * // Negates a method reference
      * Predicate isNotNull1 = not(Objects::isNull);
      * isNotNull1.test("");   // true
      * isNotNull1.test(null); // false
      *
-     * // negates a predicate instance
+     * // Negates a predicate instance
      * Predicate isNotNull2 = not(Predicates.isNull());
      * isNotNull2.test("");   // true
      * isNotNull2.test(null); // false
      * }
* - * @param predicate A {@code Predicate} that tests elements of type {@code T} - * @param tested object type - * @return A new {@code Predicate} + * @param predicate the predicate to negate + * @param the type of objects being tested + * @return a predicate that evaluates to {@code true} if the original predicate evaluates to {@code false}, and vice versa * @throws NullPointerException if {@code predicate} is null */ @SuppressWarnings("unchecked") @@ -266,5 +291,4 @@ public static Predicate not(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return (Predicate) predicate.negate(); } - } diff --git a/vavr/src/main/java/io/vavr/Value.java b/vavr/src/main/java/io/vavr/Value.java index 1895f592f..b7536ef6e 100644 --- a/vavr/src/main/java/io/vavr/Value.java +++ b/vavr/src/main/java/io/vavr/Value.java @@ -53,12 +53,12 @@ import static io.vavr.API.*; /** - * Functional programming is all about values and transformation of values using functions. The {@code Value} - * type reflects the values in a functional setting. It can be seen as the result of a partial function application. - * Hence the result may be undefined. If a value is undefined, we say it is empty. + * Represents a value in a functional programming context. A {@code Value} models the outcome of a computation + * that may or may not produce a result, similar to the result of a partially applied function. *

- * How the empty state is interpreted depends on the context, i.e. it may be undefined, failed, - * no elements, etc. + * A {@code Value} may be present or absent. When absent, it is considered empty. The meaning of the + * empty state depends on the concrete implementation and usage context - it may represent an undefined value, + * a failed computation, or the absence of elements. *

* Basic operations: * diff --git a/vavr/src/main/java/io/vavr/concurrent/Future.java b/vavr/src/main/java/io/vavr/concurrent/Future.java index c830df4ac..c106bcabd 100644 --- a/vavr/src/main/java/io/vavr/concurrent/Future.java +++ b/vavr/src/main/java/io/vavr/concurrent/Future.java @@ -35,23 +35,25 @@ import java.util.function.*; /** - * A Future is a computation result that becomes available at some point. All operations provided are non-blocking. - *

- * The underlying {@code Executor} is used to execute asynchronous handlers, e.g. via - * {@code onComplete(...)}. - *

- * A Future has two states: pending and completed. + * Represents the result of an asynchronous computation that becomes available at some point in the future. + * All operations provided by this {@code Future} are non-blocking. + * + *

The underlying {@link java.util.concurrent.Executor} is used to execute asynchronous handlers, for example via + * {@code onComplete(...)}.

+ * + *

A {@code Future} has two states:

*
    - *
  • Pending: The computation is ongoing. Only a pending future may be completed or cancelled.
  • - *
  • Completed: The computation finished successfully with a result, failed with an exception or was cancelled.
  • + *
  • Pending: The computation is ongoing. Only a pending future may be completed or cancelled.
  • + *
  • Completed: The computation has finished, either successfully with a result, with an exception, or via cancellation.
  • *
- * Callbacks may be registered on a Future at each point of time. These actions are performed as soon as the Future - * is completed. An action which is registered on a completed Future is immediately performed. The action may run on - * a separate Thread, depending on the underlying Executor. Actions which are registered on a cancelled - * Future are performed with the failed result. * - * @param Type of the computation result. - * @author Daniel Dietrich + *

Callbacks may be registered on a {@code Future} at any time. These callbacks are executed as soon as the + * {@code Future} completes. If a callback is registered on a completed {@code Future}, it is executed immediately. + * Execution may occur on a separate thread, depending on the underlying {@code Executor}. Callbacks registered + * on a cancelled {@code Future} are executed with the failed result.

+ * + * @param the type of the computation result + * @author Daniel Dietrich, Grzegorz Piwowarek */ @SuppressWarnings("deprecation") public interface Future extends Value { @@ -80,7 +82,7 @@ public interface Future extends Value { * @see ForkJoinPool#awaitQuiescence(long, TimeUnit) * @deprecated Will be removed in Vavr 1.0. Use {@link #DEFAULT_EXECUTOR instead}. */ - @Deprecated + @Deprecated() ExecutorService DEFAULT_EXECUTOR_SERVICE = ForkJoinPool.commonPool(); /** @@ -109,12 +111,13 @@ public interface Future extends Value { Executor DEFAULT_EXECUTOR = DEFAULT_EXECUTOR_SERVICE; /** - * Creates a failed {@code Future} with the given {@code exception}, backed by the {@link #DEFAULT_EXECUTOR}. + * Creates a failed {@code Future} with the given {@code exception}, using the {@link #DEFAULT_EXECUTOR} + * to execute callbacks. * - * @param exception The reason why it failed. - * @param The value type of a successful result. - * @return A failed {@code Future}. - * @throws NullPointerException if exception is null + * @param exception the exception that caused the failure + * @param the type of a successful result + * @return a failed {@code Future} containing the given exception + * @throws NullPointerException if {@code exception} is null */ static Future failed(Throwable exception) { Objects.requireNonNull(exception, "exception is null"); @@ -122,13 +125,13 @@ static Future failed(Throwable exception) { } /** - * Creates a failed {@code Future} with the given {@code exception}, backed by the given {@link Executor}. + * Creates a failed {@code Future} with the given {@code exception}, executing callbacks using the specified {@link Executor}. * - * @param executor An {@link Executor}. - * @param exception The reason why it failed. - * @param The value type of a successful result. - * @return A failed {@code Future}. - * @throws NullPointerException if executor or exception is null + * @param executor the {@link Executor} to run asynchronous handlers + * @param exception the exception that caused the failure + * @param the type of a successful result + * @return a failed {@code Future} containing the given exception + * @throws NullPointerException if {@code executor} or {@code exception} is null */ static Future failed(Executor executor, Throwable exception) { Objects.requireNonNull(executor, "executor is null"); @@ -137,33 +140,33 @@ static Future failed(Executor executor, Throwable exception) { } /** - * Returns a {@code Future} that eventually succeeds with the first result of the given {@code Future}s which - * matches the given {@code predicate}. If no result matches, the {@code Future} will contain {@link Option.None}. - *

- * The returned {@code Future} is backed by the {@link #DEFAULT_EXECUTOR}. + * Returns a {@code Future} that completes with the first result of the given {@code futures} + * that satisfies the specified {@code predicate}. If no result matches, the {@code Future} will contain {@link Option.None}. * - * @param futures An iterable of futures. - * @param predicate A predicate that tests successful future results. - * @param Result type of the futures. - * @return A Future of an {@link Option} of the first result of the given {@code futures} that satisfies the given {@code predicate}. - * @throws NullPointerException if one of the arguments is null + *

The returned {@code Future} uses the {@link #DEFAULT_EXECUTOR} to execute callbacks.

+ * + * @param futures an iterable of futures to inspect + * @param predicate a predicate to test successful future results + * @param the type of the future results + * @return a {@code Future} of an {@link Option} containing the first matching result, or {@link Option.None} if none match + * @throws NullPointerException if {@code futures} or {@code predicate} is null */ static Future> find(Iterable> futures, Predicate predicate) { return find(DEFAULT_EXECUTOR, futures, predicate); } /** - * Returns a {@code Future} that eventually succeeds with the first result of the given {@code Future}s which - * matches the given {@code predicate}. If no result matches, the {@code Future} will contain {@link Option.None}. - *

- * The returned {@code Future} is backed by the given {@link Executor}. + * Returns a {@code Future} that completes with the first result of the given {@code futures} + * that satisfies the specified {@code predicate}. If no result matches, the {@code Future} will contain {@link Option.None}. + * + *

The returned {@code Future} executes using the provided {@link Executor}.

* - * @param executor An {@link Executor}. - * @param futures An iterable of futures. - * @param predicate A predicate that tests successful future results. - * @param Result type of the futures. - * @return A Future of an {@link Option} of the first result of the given {@code futures} that satisfies the given {@code predicate}. - * @throws NullPointerException if one of the arguments is null + * @param executor the {@link Executor} to run asynchronous handlers + * @param futures an iterable of futures to inspect + * @param predicate a predicate to test successful future results + * @param the type of the future results + * @return a {@code Future} of an {@link Option} containing the first matching result, or {@link Option.None} if none match + * @throws NullPointerException if any argument is null */ static Future> find(Executor executor, Iterable> futures, Predicate predicate) { Objects.requireNonNull(executor, "executor is null"); @@ -202,27 +205,27 @@ static Future> find(Executor executor, Iterable The result type. - * @return A new {@code Future}. - * @throws NullPointerException if futures is null + * @param futures an iterable of futures to observe + * @param the type of the future results + * @return a new {@code Future} containing the result of the first completed future + * @throws NullPointerException if {@code futures} is null */ static Future firstCompletedOf(Iterable> futures) { return firstCompletedOf(DEFAULT_EXECUTOR, futures); } /** - * Returns a new {@code Future} that will contain the result of the first of the given futures that is completed, - * backed by the given {@link Executor}. + * Returns a new {@code Future} that completes with the result of the first future in the given iterable + * that completes, using the specified {@link Executor}. * - * @param executor An {@link Executor}. - * @param futures An iterable of futures. - * @param The result type. - * @return A new {@code Future}. - * @throws NullPointerException if executor or futures is null + * @param executor the {@link Executor} to run asynchronous handlers + * @param futures an iterable of futures to observe + * @param the type of the future results + * @return a new {@code Future} containing the result of the first completed future + * @throws NullPointerException if {@code executor} or {@code futures} is null */ static Future firstCompletedOf(Executor executor, Iterable> futures) { Objects.requireNonNull(executor, "executor is null"); @@ -231,37 +234,37 @@ static Future firstCompletedOf(Executor executor, Iterable - * The resulting {@code Future} is backed by the {@link #DEFAULT_EXECUTOR}. + * Returns a {@code Future} that contains the result of folding the given future values. + * If any future fails or the fold operation throws an exception, the resulting {@code Future} will also fail. + * + *

The resulting {@code Future} executes using the {@link #DEFAULT_EXECUTOR}.

* - * @param futures An iterable of futures. - * @param zero The zero element of the fold. - * @param f The fold operation. - * @param The result type of the given {@code Futures}. - * @param The fold result type. - * @return A new {@code Future} that will contain the fold result. - * @throws NullPointerException if futures or f is null. + * @param futures an iterable of futures to fold + * @param zero the initial value for the fold + * @param f the fold operation + * @param the type of the values in the given futures + * @param the result type of the fold + * @return a new {@code Future} containing the fold result + * @throws NullPointerException if {@code futures} or {@code f} is null */ static Future fold(Iterable> futures, U zero, BiFunction f) { return fold(DEFAULT_EXECUTOR, futures, zero, f); } /** - * Returns a Future which contains the result of the fold of the given future values. If any future or the fold - * fail, the result is a failure. - *

- * The resulting {@code Future} is backed by the given {@link Executor}. + * Returns a {@code Future} containing the result of folding the given future values. + * If any future fails or the fold operation throws an exception, the resulting {@code Future} will also fail. + * + *

The resulting {@code Future} executes using the specified {@link Executor}.

* - * @param executor An {@link Executor}. - * @param futures An iterable of futures. - * @param zero The zero element of the fold. - * @param f The fold operation. - * @param The result type of the given {@code Futures}. - * @param The fold result type. - * @return A new {@code Future} that will contain the fold result. - * @throws NullPointerException if executor, futures or f is null. + * @param executor the {@link Executor} to run asynchronous handlers + * @param futures an iterable of futures to fold + * @param zero the initial value for the fold + * @param f the fold operation + * @param the type of the values in the given futures + * @param the result type of the fold + * @return a new {@code Future} containing the fold result + * @throws NullPointerException if {@code executor}, {@code futures}, or {@code f} is null */ static Future fold(Executor executor, Iterable> futures, U zero, BiFunction f) { Objects.requireNonNull(executor, "executor is null"); @@ -275,12 +278,13 @@ static Future fold(Executor executor, Iterable Result type of the Future - * @return A new {@code Future} wrapping the result of the Java future - * @throws NullPointerException if future is null + * @param future the {@link java.util.concurrent.Future} to wrap + * @param the result type of the future + * @return a new {@code Future} containing the result of the given Java future + * @throws NullPointerException if {@code future} is null */ static Future fromJavaFuture(java.util.concurrent.Future future) { Objects.requireNonNull(future, "future is null"); @@ -288,13 +292,14 @@ static Future fromJavaFuture(java.util.concurrent.Future future) { } /** - * Creates a {@code Future} with the given java.util.concurrent.Future, backed by given {@link Executor} + * Creates a {@code Future} that wraps the given {@link java.util.concurrent.Future}, + * executing callbacks using the specified {@link Executor}. * - * @param executor An {@link Executor}. - * @param future A {@link java.util.concurrent.Future}. - * @param Result type of the Future - * @return A new {@code Future} wrapping the result of the Java future - * @throws NullPointerException if executor or future is null + * @param executor the {@link Executor} to run asynchronous handlers + * @param future the {@link java.util.concurrent.Future} to wrap + * @param the result type of the future + * @return a new {@code Future} containing the result of the given Java future + * @throws NullPointerException if {@code executor} or {@code future} is null */ static Future fromJavaFuture(Executor executor, java.util.concurrent.Future future) { Objects.requireNonNull(executor, "executor is null"); @@ -303,12 +308,13 @@ static Future fromJavaFuture(Executor executor, java.util.concurrent.Futu } /** - * Creates a {@code Future} with the given {@link java.util.concurrent.CompletableFuture}, backed by the {@link #DEFAULT_EXECUTOR} + * Creates a {@code Future} that wraps the given {@link java.util.concurrent.CompletableFuture}, + * using the {@link #DEFAULT_EXECUTOR} for executing callbacks. * - * @param future A {@link java.util.concurrent.CompletableFuture} - * @param Result type of the Future - * @return A new {@code Future} wrapping the result of the {@link java.util.concurrent.CompletableFuture} - * @throws NullPointerException if future is null + * @param future the {@link java.util.concurrent.CompletableFuture} to wrap + * @param the result type of the future + * @return a new {@code Future} containing the result of the given {@link java.util.concurrent.CompletableFuture} + * @throws NullPointerException if {@code future} is null */ @GwtIncompatible static Future fromCompletableFuture(CompletableFuture future) { @@ -316,13 +322,14 @@ static Future fromCompletableFuture(CompletableFuture future) { } /** - * Creates a {@code Future} with the given {@link java.util.concurrent.CompletableFuture}, backed by given {@link Executor} + * Creates a {@code Future} that wraps the given {@link java.util.concurrent.CompletableFuture}, + * executing callbacks using the specified {@link Executor}. * - * @param executor An {@link Executor}. - * @param future A {@link java.util.concurrent.CompletableFuture}. - * @param Result type of the Future - * @return A new {@code Future} wrapping the result of the {@link java.util.concurrent.CompletableFuture} - * @throws NullPointerException if executor or future is null + * @param executor the {@link Executor} to run asynchronous handlers + * @param future the {@link java.util.concurrent.CompletableFuture} to wrap + * @param the result type of the future + * @return a new {@code Future} containing the result of the given {@link java.util.concurrent.CompletableFuture} + * @throws NullPointerException if {@code executor} or {@code future} is null */ @GwtIncompatible static Future fromCompletableFuture(Executor executor, CompletableFuture future) { @@ -338,25 +345,25 @@ static Future fromCompletableFuture(Executor executor, CompletableFuture< } /** - * Creates a {@code Future} from a {@link Try}, backed by the {@link #DEFAULT_EXECUTOR}. + * Creates a {@code Future} from a {@link Try}, using the {@link #DEFAULT_EXECUTOR}. * - * @param result The result. - * @param The value type of a successful result. - * @return A completed {@code Future} which contains either a {@code Success} or a {@code Failure}. - * @throws NullPointerException if result is null + * @param result the {@link Try} result to wrap + * @param the type of a successful result + * @return a completed {@code Future} containing either a {@code Success} or a {@code Failure} + * @throws NullPointerException if {@code result} is null */ static Future fromTry(Try result) { return fromTry(DEFAULT_EXECUTOR, result); } /** - * Creates a {@code Future} from a {@link Try}, backed by the given {@link Executor}. + * Creates a {@code Future} from a {@link Try}, executing callbacks using the specified {@link Executor}. * - * @param executor An {@link Executor}. - * @param result The result. - * @param The value type of a successful result. - * @return A completed {@code Future} which contains either a {@code Success} or a {@code Failure}. - * @throws NullPointerException if executor or result is null + * @param executor the {@link Executor} to run asynchronous handlers + * @param result the {@link Try} result to wrap + * @param the type of successful result + * @return a completed {@code Future} containing either a {@code Success} or a {@code Failure} + * @throws NullPointerException if {@code executor} or {@code result} is null */ static Future fromTry(Executor executor, Try result) { Objects.requireNonNull(executor, "executor is null"); @@ -365,13 +372,12 @@ static Future fromTry(Executor executor, Try result) { } /** - * Narrows a widened {@code Future} to {@code Future} - * by performing a type-safe cast. This is eligible because immutable/read-only - * collections are covariant. + * Narrows a {@code Future} to {@code Future} via a type-safe cast. + * This is safe because immutable or read-only collections are covariant. * - * @param future A {@code Future}. - * @param Component type of the {@code Future}. - * @return the given {@code future} instance as narrowed type {@code Future}. + * @param future the {@code Future} to narrow + * @param the type of the value contained in the future + * @return the given {@code future} instance as a {@code Future} */ @SuppressWarnings("unchecked") static Future narrow(Future future) { @@ -379,13 +385,13 @@ static Future narrow(Future future) { } /** - * Starts an asynchronous computation, backed by the {@link #DEFAULT_EXECUTOR}. + * Starts an asynchronous computation using the {@link #DEFAULT_EXECUTOR}. * - * @param computation A computation. - * @param Type of the computation result. - * @return A new Future instance - * @throws NullPointerException if computation is null. - * @deprecated Will be removed. Use {@code Future.of(supplier::get)} instead of {@code Future.ofSupplier(supplier)}. + * @param computation the computation to execute asynchronously + * @param the type of the computation result + * @return a new {@code Future} containing the result of the computation + * @throws NullPointerException if {@code computation} is null + * @deprecated This method will be removed. Use {@code Future.of(supplier::get)} instead of {@code Future.ofSupplier(supplier)}. */ @Deprecated static Future ofSupplier(Supplier computation) { @@ -473,25 +479,25 @@ static Future runRunnable(Executor executor, Runnable computation) { } /** - * Starts an asynchronous computation, backed by the {@link #DEFAULT_EXECUTOR}. + * Starts an asynchronous computation using the {@link #DEFAULT_EXECUTOR}. * - * @param computation A computation. - * @param Type of the computation result. - * @return A new Future instance. - * @throws NullPointerException if computation is null. + * @param computation the computation to execute asynchronously + * @param the type of the computation result + * @return a new {@code Future} containing the result of the computation + * @throws NullPointerException if {@code computation} is null */ static Future of(CheckedFunction0 computation) { return of(DEFAULT_EXECUTOR, computation); } /** - * Starts an asynchronous computation, backed by the given {@link Executor}. + * Starts an asynchronous computation using the specified {@link Executor}. * - * @param executor An {@link Executor}. - * @param computation A computation. - * @param Type of the computation result. - * @return A new Future instance. - * @throws NullPointerException if one of executor or computation is null. + * @param executor the {@link Executor} to run asynchronous handlers + * @param computation the computation to execute asynchronously + * @param the type of the computation result + * @return a new {@code Future} containing the result of the computation + * @throws NullPointerException if {@code executor} or {@code computation} is null */ static Future of(Executor executor, CheckedFunction0 computation) { Objects.requireNonNull(executor, "executor is null"); @@ -577,33 +583,35 @@ static Future run(Executor executor, Task task) { } /** - * Returns a Future which contains the reduce result of the given future values. The zero is the result of the - * first future that completes. If any future or the reduce operation fail, the result is a failure. - *

- * The resulting {@code Future} is backed by the {@link #DEFAULT_EXECUTOR}. + * Returns a {@code Future} containing the result of reducing the given future values. + * The first completed future serves as the initial (zero) value. + * If any future or the reduce operation fails, the resulting {@code Future} will also fail. * - * @param futures An iterable of futures. - * @param f The reduce operation. - * @param The result type of the given {@code Futures}. - * @return A new {@code Future} that will contain the reduce result. - * @throws NullPointerException if executor, futures or f is null. + *

The resulting {@code Future} executes using the {@link #DEFAULT_EXECUTOR}.

+ * + * @param futures an iterable of futures to reduce + * @param f the reduce operation + * @param the type of the values in the given futures + * @return a new {@code Future} containing the reduce result + * @throws NullPointerException if {@code futures} or {@code f} is null */ static Future reduce(Iterable> futures, BiFunction f) { return reduce(DEFAULT_EXECUTOR, futures, f); } /** - * Returns a Future which contains the reduce result of the given future values. The zero is the result of the - * first future that completes. If any future or the reduce operation fail, the result is a failure. - *

- * The resulting {@code Future} is backed by the given {@link Executor}. + * Returns a {@code Future} containing the result of reducing the given future values. + * The first completed future serves as the initial (zero) value. + * If any future or the reduce operation fails, the resulting {@code Future} will also fail. * - * @param executor An {@link Executor}. - * @param futures An iterable of futures. - * @param f The reduce operation. - * @param The result type of the given {@code Futures}. - * @return A new {@code Future} that will contain the reduce result. - * @throws NullPointerException if executor, futures or f is null. + *

The resulting {@code Future} executes using the specified {@link Executor}.

+ * + * @param executor the {@link Executor} to run asynchronous handlers + * @param futures an iterable of futures to reduce + * @param f the reduce operation + * @param the type of the values in the given futures + * @return a new {@code Future} containing the reduce result + * @throws NullPointerException if {@code executor}, {@code futures}, or {@code f} is null */ static Future reduce(Executor executor, Iterable> futures, BiFunction f) { Objects.requireNonNull(executor, "executor is null"); @@ -617,24 +625,25 @@ static Future reduce(Executor executor, Iterable run(CheckedRunnable unit) { return run(DEFAULT_EXECUTOR, unit); } /** - * Starts an asynchronous computation, backed by the given {@link Executor}. + * Starts an asynchronous computation using the specified {@link Executor}. * - * @param executor An {@link Executor}. - * @param unit A unit of work. - * @return A new Future instance which results in nothing. - * @throws NullPointerException if one of executor or unit is null. + * @param executor the {@link Executor} to run asynchronous handlers + * @param unit a unit of work to execute asynchronously + * @return a new {@code Future} representing the completion of the computation, with no result + * @throws NullPointerException if {@code executor} or {@code unit} is null */ + static Future run(Executor executor, CheckedRunnable unit) { Objects.requireNonNull(executor, "executor is null"); Objects.requireNonNull(unit, "unit is null"); @@ -645,54 +654,58 @@ static Future run(Executor executor, CheckedRunnable unit) { } /** - * Reduces many {@code Future}s into a single {@code Future} by transforming an + * Reduces multiple {@code Future} instances into a single {@code Future} by transforming an * {@code Iterable>} into a {@code Future>}. - *

- * The resulting {@code Future} is backed by the {@link #DEFAULT_EXECUTOR}. + * + *

The resulting {@code Future} executes using the {@link #DEFAULT_EXECUTOR}.

* *
    - *
  • - * If all of the given Futures succeed, sequence() succeeds too: - *
    // = Future(Success(Seq(1, 2)))
    +     *     
  • + * If all given futures succeed, the resulting future also succeeds: + *
    
    +     * // = Future(Success(Seq(1, 2)))
          * sequence(
          *     List.of(
    -     *         Future.of(() -> 1),
    -     *         Future.of(() -> 2)
    +     *         Future.of(() -> 1),
    +     *         Future.of(() -> 2)
          *     )
    -     * );
    - *
  • - *
  • - * If a given Future fails, sequence() fails too: - *
    // = Future(Failure(Error)))
    +     * );
    +     *         
    + *
  • + *
  • + * If any given future fails, the resulting future fails as well: + *
    
    +     * // = Future(Failure(Error))
          * sequence(
          *     List.of(
    -     *         Future.of(() -> 1),
    -     *         Future.of(() -> { throw new Error(); }
    +     *         Future.of(() -> 1),
    +     *         Future.of(() -> { throw new Error(); })
          *     )
    -     * );
    - *
  • + * ); + *
    + *
  • *
* - * @param futures An {@code Iterable} of {@code Future}s. - * @param Result type of the futures. - * @return A {@code Future} of a {@link Seq} of results. - * @throws NullPointerException if futures is null. + * @param futures an {@code Iterable} of {@code Future}s + * @param the result type of the futures + * @return a {@code Future} containing a {@link Seq} of results + * @throws NullPointerException if {@code futures} is null */ static Future> sequence(Iterable> futures) { return sequence(DEFAULT_EXECUTOR, futures); } /** - * Reduces many {@code Future}s into a single {@code Future} by transforming an + * Reduces multiple {@code Future} instances into a single {@code Future} by transforming an * {@code Iterable>} into a {@code Future>}. - *

- * The resulting {@code Future} is backed by the given {@link Executor}. * - * @param executor An {@link Executor}. - * @param futures An {@code Iterable} of {@code Future}s. - * @param Result type of the futures. - * @return A {@code Future} of a {@link Seq} of results. - * @throws NullPointerException if executor or futures is null. + *

The resulting {@code Future} executes using the specified {@link Executor}.

+ * + * @param executor the {@link Executor} to run asynchronous handlers + * @param futures an {@code Iterable} of {@code Future}s to reduce + * @param the result type of the futures + * @return a {@code Future} containing a {@link Seq} of results + * @throws NullPointerException if {@code executor} or {@code futures} is null */ static Future> sequence(Executor executor, Iterable> futures) { Objects.requireNonNull(executor, "executor is null"); @@ -704,24 +717,25 @@ static Future> sequence(Executor executor, Iterable The value type of a successful result. - * @return A succeeded {@code Future}. + * @param result the successful result + * @param the type of the result + * @return a succeeded {@code Future} containing the given result */ static Future successful(T result) { return successful(DEFAULT_EXECUTOR, result); } /** - * Creates a succeeded {@code Future}, backed by the given {@link Executor}. + * Creates a succeeded {@code Future} with the given result, executing callbacks using the specified {@link Executor}. * - * @param executor An {@link Executor}. - * @param result The result. - * @param The value type of a successful result. - * @return A succeeded {@code Future}. - * @throws NullPointerException if executor is null + * @param executor the {@link Executor} to run asynchronous handlers + * @param result the successful result + * @param the type of the result + * @return a succeeded {@code Future} containing the given result + * @throws NullPointerException if {@code executor} is null */ static Future successful(Executor executor, T result) { Objects.requireNonNull(executor, "executor is null"); @@ -738,35 +752,35 @@ default CompletableFuture toCompletableFuture() { } /** - * Maps the values of an iterable in parallel to a sequence of mapped values into a single {@code Future} by - * transforming an {@code Iterable} into a {@code Future>}. - *

- * The resulting {@code Future} is backed by the {@link #DEFAULT_EXECUTOR}. + * Maps the values of an iterable in parallel to a sequence of mapped values, producing a single {@code Future} + * by transforming an {@code Iterable} into a {@code Future>}. + * + *

The resulting {@code Future} executes using the {@link #DEFAULT_EXECUTOR}.

* - * @param values An {@code Iterable} of {@code Future}s. - * @param mapper A mapper of values to Futures - * @param The type of the given values. - * @param The mapped value type. - * @return A {@code Future} of a {@link Seq} of results. - * @throws NullPointerException if values or f is null. + * @param values an {@code Iterable} of input values + * @param mapper a function mapping values to {@code Future}s + * @param the type of the input values + * @param the type of the mapped values + * @return a {@code Future} containing a {@link Seq} of mapped results + * @throws NullPointerException if {@code values} or {@code mapper} is null */ static Future> traverse(Iterable values, Function> mapper) { return traverse(DEFAULT_EXECUTOR, values, mapper); } /** - * Maps the values of an iterable in parallel to a sequence of mapped values into a single {@code Future} by - * transforming an {@code Iterable} into a {@code Future>}. - *

- * The resulting {@code Future} is backed by the given {@link Executor}. + * Maps the values of an iterable in parallel to a sequence of mapped values, producing a single {@code Future} + * by transforming an {@code Iterable} into a {@code Future>}. + * + *

The resulting {@code Future} executes using the specified {@link Executor}.

* - * @param executor An {@link Executor}. - * @param values An {@code Iterable} of values. - * @param mapper A mapper of values to Futures - * @param The type of the given values. - * @param The mapped value type. - * @return A {@code Future} of a {@link Seq} of results. - * @throws NullPointerException if executor, values or f is null. + * @param executor the {@link Executor} to run asynchronous handlers + * @param values an {@code Iterable} of input values + * @param mapper a function mapping values to {@code Future}s + * @param the type of the input values + * @param the type of the mapped values + * @return a {@code Future} containing a {@link Seq} of mapped results + * @throws NullPointerException if {@code executor}, {@code values}, or {@code mapper} is null */ static Future> traverse(Executor executor, Iterable values, Function> mapper) { Objects.requireNonNull(executor, "executor is null"); @@ -778,22 +792,22 @@ static Future> traverse(Executor executor, Iterable v // -- non-static Future API /** - * Support for chaining of callbacks that are guaranteed to be executed in a specific order. - *

- * An exception, which occurs when performing the given {@code action}, is not propagated to the outside. - * In other words, subsequent actions are performed based on the value of the original Future. - *

- * Example: + * Supports chaining of callbacks that are guaranteed to be executed in order. + * + *

Exceptions thrown by the given {@code action} are not propagated. Subsequent actions + * are executed based on the value of the original {@code Future}.

+ * + *

Example:

*

      * // prints Success(1)
-     * Future.of(() -> 1)
-     *       .andThen(t -> { throw new Error(""); })
+     * Future.of(() -> 1)
+     *       .andThen(t -> { throw new Error(""); })
      *       .andThen(System.out::println);
      * 
* - * @param action A side-effecting action. - * @return A new Future that contains this result and which is completed after the given action was performed. - * @throws NullPointerException if action is null + * @param action a side-effecting action to perform after the future completes + * @return a new {@code Future} containing the original result, completed after the action executes + * @throws NullPointerException if {@code action} is null */ default Future andThen(Consumer> action) { Objects.requireNonNull(action, "action is null"); @@ -806,22 +820,23 @@ default Future andThen(Consumer> action) { } /** - * Blocks the current Thread until this Future completed or returns immediately if this Future is already completed. - *

- * In the case the current thread was interrupted while waiting, a failed {@code Future} is returned containing - * the corresponding {@link InterruptedException}. + * Blocks the current thread until this {@code Future} is completed, or returns immediately if it is already completed. + * + *

If the current thread is interrupted while waiting, a failed {@code Future} is returned containing + * the corresponding {@link InterruptedException}.

* * @return this {@code Future} instance */ Future await(); /** - * Blocks the current Thread until this Future completed or returns immediately if this Future is already completed. - *

- * In the case the current thread was interrupted while waiting, a failed {@code Future} is returned containing - * the corresponding {@link InterruptedException}. - *

- * If the deadline wasn't met, a failed {@code Future} is returned containing a {@link TimeoutException}. + * Blocks the current thread until this {@code Future} is completed, or returns immediately if it is already completed. + * + *

If the current thread is interrupted while waiting, a failed {@code Future} is returned containing + * the corresponding {@link InterruptedException}.

+ * + *

If the specified timeout is reached before completion, a failed {@code Future} is returned containing + * a {@link TimeoutException}.

* * @param timeout the maximum time to wait * @param unit the time unit of the timeout argument @@ -832,12 +847,12 @@ default Future andThen(Consumer> action) { Future await(long timeout, TimeUnit unit); /** - * Cancels the Future. A running thread is interrupted. - *

- * If the Future was successfully cancelled, the result is a {@code Failure(CancellationException)}. + * Cancels this {@code Future}. If it is running, the executing thread is interrupted. + * + *

If the future is successfully cancelled, its result becomes a {@code Failure(CancellationException)}.

* - * @return {@code false}, if this {@code Future} is already completed or could not be cancelled, otherwise {@code true}. - * @throws SecurityException if the current thread cannot modify the Future's thread + * @return {@code false} if this {@code Future} is already completed or could not be cancelled, {@code true} otherwise + * @throws SecurityException if the current thread is not permitted to modify the Future's thread * @see Future#isCancelled() */ default boolean cancel() { @@ -845,35 +860,32 @@ default boolean cancel() { } /** - * Cancels the Future. A pending Future may be interrupted, depending on the underlying {@code Executor}. - *

- * If the Future was successfully cancelled, the result is a {@code Failure(CancellationException)}. + * Cancels this {@code Future}. A pending future may be interrupted depending on the underlying {@code Executor}. + * + *

If the future is successfully cancelled, its result becomes a {@code Failure(CancellationException)}.

* - * @param mayInterruptIfRunning {@code true} if a running thread should be interrupted, otherwise a running thread - * is allowed to complete its computation. - * @return {@code false}, if this {@code Future} is already completed or could not be cancelled, otherwise {@code true}. - * @throws SecurityException if the current thread cannot modify the Future's thread + * @param mayInterruptIfRunning {@code true} if a running thread should be interrupted; {@code false} allows it to complete + * @return {@code false} if this {@code Future} is already completed or could not be cancelled, {@code true} otherwise + * @throws SecurityException if the current thread is not permitted to modify the Future's thread * @see Future#isCancelled() * @see java.util.concurrent.Future#cancel(boolean) */ boolean cancel(boolean mayInterruptIfRunning); /** - * Collects value that is in the domain of the given {@code partialFunction} by mapping the value to type {@code R}. - * - *
{@code
-     * partialFunction.isDefinedAt(value)
-     * }
- * - * If the element makes it through that filter, the mapped instance is wrapped in {@code Future} + * Applies a {@code partialFunction} to the value of this {@code Future}, collecting results only for values + * where the function is defined. The mapped result is wrapped in a new {@code Future}. * + *

Example:

*
{@code
-     * R newValue = partialFunction.apply(value)
+     * if (partialFunction.isDefinedAt(value)) {
+     *     R newValue = partialFunction.apply(value);
+     * }
      * }
* - * @param partialFunction A function that is not necessarily defined on value of this future. - * @param The new value type - * @return A new {@code Future} instance containing value of type {@code R} + * @param partialFunction a function that may not be defined for every value of this future + * @param the type of the mapped result + * @return a new {@code Future} containing the mapped value * @throws NullPointerException if {@code partialFunction} is null */ default Future collect(PartialFunction partialFunction) { @@ -884,9 +896,9 @@ default Future collect(PartialFunction partialFun } /** - * Returns the {@link Executor} used by this {@code Future}. + * Returns the {@link Executor} that executes asynchronous handlers for this {@code Future}. * - * @return The underlying {@code Executor}. + * @return the underlying {@code Executor} */ default Executor executor() { return executorService(); @@ -906,13 +918,12 @@ default Executor executor() { ExecutorService executorService() throws UnsupportedOperationException; /** - * A projection that inverses the result of this Future. - *

- * If this Future succeeds, the failed projection returns a failure containing a {@code NoSuchElementException}. - *

- * If this Future fails, the failed projection returns a success containing the exception. + * Returns a projection that inverts the result of this {@code Future}. + * + *

If this {@code Future} succeeds, the resulting failed projection contains a {@code NoSuchElementException}.

+ *

If this {@code Future} fails, the resulting failed projection succeeds with the exception as its value.

* - * @return A new Future which contains an exception at a point of time. + * @return a new {@code Future} representing the inverted result */ default Future failed() { return run(executor(), complete -> @@ -927,23 +938,23 @@ default Future failed() { } /** - * Returns a Future that returns the result of this Future, if it is a success. If the value of this Future is a - * failure, the result of {@code that} Future is returned, if that is a success. If both Futures fail, the failure - * of this Future is returned. - *

- * Example: + * Returns a {@code Future} that yields the result of this {@code Future} if it succeeds. + * If this {@code Future} fails, the result of the given {@code that} {@code Future} is returned if it succeeds. + * If both {@code Future}s fail, the failure of this {@code Future} is returned. + * + *

Example:

*

-     * Future<Integer> future = Future.of(() -> { throw new Error(); });
-     * Future<Integer> that = Future.of(() -> 1);
+     * Future<Integer> future = Future.of(() -> { throw new Error(); });
+     * Future<Integer> that = Future.of(() -> 1);
      * Future<Integer> result = future.fallbackTo(that);
      *
-     * // prints Some(1)
+     * // prints Success(1)
      * result.onComplete(System.out::println);
      * 
* - * @param that A fallback future computation - * @return A new Future - * @throws NullPointerException if that is null + * @param that a fallback {@code Future} to use if this one fails + * @return a new {@code Future} representing the result or fallback + * @throws NullPointerException if {@code that} is null */ default Future fallbackTo(Future that) { Objects.requireNonNull(that, "that is null"); @@ -959,10 +970,10 @@ default Future fallbackTo(Future that) { } /** - * Shortcut for {@code filterTry(predicate::test}. + * Shortcut for {@code filterTry(predicate::test)}, filtering the result of this {@code Future} using the given predicate. * - * @param predicate A predicate - * @return A new {@code Future} + * @param predicate a predicate to test the value of the future + * @return a new {@code Future} containing the value if the predicate passes, or a failure otherwise * @throws NullPointerException if {@code predicate} is null */ default Future filter(Predicate predicate) { @@ -971,10 +982,11 @@ default Future filter(Predicate predicate) { } /** - * Filters the result of this {@code Future} by calling {@link Try#filterTry(CheckedPredicate)}. + * Filters the result of this {@code Future} using the given {@link CheckedPredicate}, delegating to + * {@link Try#filterTry(CheckedPredicate)}. * - * @param predicate A checked predicate - * @return A new {@code Future} + * @param predicate a checked predicate to test the value of the future + * @return a new {@code Future} containing the value if the predicate passes, or a failure otherwise * @throws NullPointerException if {@code predicate} is null */ default Future filterTry(CheckedPredicate predicate) { @@ -983,70 +995,73 @@ default Future filterTry(CheckedPredicate predicate) { } /** - * Returns the underlying exception of this Future, syntactic sugar for {@code future.getValue().map(Try::getCause)}. + * Returns the underlying exception. This is syntactic sugar for + * {@code future.getValue().map(Try::getCause)}. * - * @return None if the Future is not completed yet. Returns Some(Throwable) if the Future was completed with a failure. - * @throws UnsupportedOperationException if the Future was successfully completed with a value + * @return {@code None} if the {@code Future} is not yet completed, or {@code Some(Throwable)} if it completed with a failure + * @throws UnsupportedOperationException if the {@code Future} completed successfully with a value */ + default Option getCause() { return getValue().map(Try::getCause); } /** - * Returns the value of the Future. + * Returns the value of this {@code Future}. * - * @return {@code None}, if the Future is not yet completed or was cancelled, otherwise {@code Some(Try)}. + * @return {@code None} if the {@code Future} is not yet completed or was cancelled; otherwise, {@code Some(Try)} containing the result or failure */ Option> getValue(); /** - * Checks if this Future is cancelled, i.e. the thread was forced to stop before completion. + * Checks whether this {@code Future} was cancelled, i.e., its computation was interrupted before completion. * - * @return true, if the computation was cancelled, false otherwise + * @return {@code true} if the computation was cancelled, {@code false} otherwise */ boolean isCancelled(); /** - * Checks if this Future is completed, i.e. has a value. + * Checks whether this {@code Future} is completed, i.e., whether it has finished with a value, failed, or was cancelled. * - * @return true, if the computation successfully finished, failed or was cancelled, false otherwise. + * @return {@code true} if the computation has completed in any state, {@code false} otherwise */ boolean isCompleted(); /** - * Checks if this Future completed with a success. + * Checks whether this {@code Future} completed successfully. * - * @return true, if this Future completed and is a Success, false otherwise. + * @return {@code true} if this {@code Future} has completed with a successful result, {@code false} otherwise */ default boolean isSuccess() { return isCompleted() && getValue().get().isSuccess(); } /** - * Checks if this Future completed with a failure. + * Checks whether this {@code Future} completed with a failure. * - * @return true, if this Future completed and is a Failure, false otherwise. + * @return {@code true} if this {@code Future} has completed with a failure, {@code false} otherwise */ default boolean isFailure() { return isCompleted() && getValue().get().isFailure(); } /** - * Performs the action once the Future is complete. + * Performs the given action once this {@code Future} is complete. * - * @param action An action to be performed when this future is complete. - * @return this Future - * @throws NullPointerException if {@code action} is null. + * @param action an action to execute when the future completes + * @return this {@code Future} + * @throws NullPointerException if {@code action} is null */ Future onComplete(Consumer> action); /** - * Performs the action once the Future is complete and the result is a {@link Try.Failure}. Please note that the - * future is also a failure when it was cancelled. + * Performs the given action once this {@code Future} is complete and its result is a {@link Try.Failure}. + *

+ * Note that a cancelled {@code Future} is also considered a failure. * - * @param action An action to be performed when this future failed. - * @return this Future - * @throws NullPointerException if {@code action} is null. + * @param action an action to execute when this future fails + * @return this {@code Future} + * @throws NullPointerException if {@code action} is null */ default Future onFailure(Consumer action) { Objects.requireNonNull(action, "action is null"); @@ -1054,11 +1069,11 @@ default Future onFailure(Consumer action) { } /** - * Performs the action once the Future is complete and the result is a {@link Try.Success}. + * Performs the given action once this {@code Future} is complete and its result is a {@link Try.Success}. * - * @param action An action to be performed when this future succeeded. - * @return this Future - * @throws NullPointerException if {@code action} is null. + * @param action an action to execute when this future succeeds + * @return this {@code Future} + * @throws NullPointerException if {@code action} is null */ default Future onSuccess(Consumer action) { Objects.requireNonNull(action, "action is null"); @@ -1066,16 +1081,17 @@ default Future onSuccess(Consumer action) { } /** - * Handles a failure of this Future by returning another result. - *

- * Example: + * Handles a failure of this {@code Future} by mapping the exception to a new result. + * + *

Example:

*

      * // = "oh!"
-     * Future.of(() -> new Error("oh!")).recover(Throwable::getMessage);
+     * Future.of(() -> { throw new Error("oh!"); })
+     *       .recover(Throwable::getMessage);
      * 
* - * @param f A function which takes the exception of a failure and returns a new value. - * @return A new Future. + * @param f a function that maps the failure exception to a new value + * @return a new {@code Future} containing either the original success or the recovered value * @throws NullPointerException if {@code f} is null */ default Future recover(Function f) { @@ -1084,16 +1100,17 @@ default Future recover(Function f) { } /** - * Handles a failure of this Future by returning the result of another Future. - *

- * Example: + * Handles a failure of this {@code Future} by returning the result of another {@code Future}. + * + *

Example:

*

      * // = "oh!"
-     * Future.of(() -> { throw new Error("oh!"); }).recoverWith(x -> Future.of(x::getMessage));
+     * Future.of(() -> { throw new Error("oh!"); })
+     *       .recoverWith(ex -> Future.of(() -> ex.getMessage()));
      * 
* - * @param f A function which takes the exception of a failure and returns a new future. - * @return A new Future. + * @param f a function that maps the failure exception to a new {@code Future} + * @return a new {@code Future} containing either the original success or the result of the recovered {@code Future} * @throws NullPointerException if {@code f} is null */ default Future recoverWith(Function> f) { @@ -1111,11 +1128,11 @@ default Future recoverWith(Function Type of transformation result - * @return An instance of type {@code U} + * @param f a function to transform the result + * @param the type of the transformed result + * @return a new {@code Future} containing the transformed result * @throws NullPointerException if {@code f} is null */ default U transform(Function, ? extends U> f) { @@ -1124,11 +1141,11 @@ default U transform(Function, ? extends U> f) { } /** - * Transforms the value of this {@code Future}, whether it is a success or a failure. + * Transforms the value of this {@code Future}, regardless of whether it completed successfully or with a failure. * - * @param f A transformation - * @param Generic type of transformation {@code Try} result - * @return A {@code Future} of type {@code U} + * @param f a function to transform the {@link Try} result + * @param the type of the transformed {@code Try} result + * @return a new {@code Future} containing the transformed result * @throws NullPointerException if {@code f} is null */ default Future transformValue(Function, ? extends Try> f) { @@ -1141,14 +1158,14 @@ default Future transformValue(Function, ? extends Try - * If this Future failed the result contains this failure. Otherwise the result contains that failure or - * a tuple of both successful Future results. + * If this {@code Future} fails, the resulting {@code Future} contains this failure. Otherwise, it contains + * the failure of {@code that} {@code Future}, or a tuple of both successful results if both succeed. * - * @param that Another Future - * @param Result type of {@code that} - * @return A new Future that returns both Future results. + * @param that another {@code Future} to combine with + * @param the result type of {@code that} + * @return a new {@code Future} containing either a failure or a tuple of both results * @throws NullPointerException if {@code that} is null */ default Future> zip(Future that) { @@ -1157,17 +1174,17 @@ default Future> zip(Future that) { } /** - * Returns a this and that Future result combined using a given combinator function. + * Combines this {@code Future} with another {@code Future} using the given combinator function. *

- * If this Future failed the result contains this failure. Otherwise the result contains that failure or - * a combination of both successful Future results. - * - * @param that Another Future - * @param combinator The combinator function - * @param Result type of {@code that} - * @param Result type of {@code f} - * @return A new Future that returns both Future results. - * @throws NullPointerException if {@code that} is null + * If this {@code Future} fails, the resulting {@code Future} contains this failure. Otherwise, it contains + * the failure of {@code that} {@code Future}, or the result of applying the combinator function to both successful results. + * + * @param that another {@code Future} to combine with + * @param combinator a function to combine the successful results of both futures + * @param the result type of {@code that} + * @param the result type of the combined value + * @return a new {@code Future} containing either a failure or the combined result + * @throws NullPointerException if {@code that} or {@code combinator} is null */ @SuppressWarnings({"deprecation", "unchecked"}) default Future zipWith(Future that, BiFunction combinator) { @@ -1205,10 +1222,12 @@ default Future flatMapTry(CheckedFunction1 + * The {@code action} is not executed if the {@code Future} completes with a failure. * - * @param action A {@code Consumer} + * @param action a {@code Consumer} to be executed with the successful result + * @throws NullPointerException if {@code action} is null */ @Override default void forEach(Consumer action) { @@ -1217,12 +1236,12 @@ default void forEach(Consumer action) { } /** - * Gets the value if the computation result is a {@code Success} or throws if it was a {@code Failure}. - * Waits for the result if necessary by blocking the current thread. - *

- * IMPORTANT! If the computation result is a {@link Try.Failure}, the underlying {@code cause} of type {@link Throwable} is thrown. + * Returns the value of this {@code Future} if it completed successfully, or throws the underlying exception + * if it completed with a failure. Blocks the current thread if the computation is not yet finished. + * + *

Note: If the computation failed, the underlying {@link Throwable} cause is thrown.

* - * @return The value of this {@code Future}. + * @return the successful result of this {@code Future} */ @Override default T get() { diff --git a/vavr/src/main/java/io/vavr/concurrent/Promise.java b/vavr/src/main/java/io/vavr/concurrent/Promise.java index ba0e89598..91244bd45 100644 --- a/vavr/src/main/java/io/vavr/concurrent/Promise.java +++ b/vavr/src/main/java/io/vavr/concurrent/Promise.java @@ -27,62 +27,63 @@ import static io.vavr.concurrent.Future.DEFAULT_EXECUTOR; /** - * A Promise is a write-once wrapper around a read-only Future which can complete the underlying Future with a value - * or an exception. + * A {@code Promise} is a write-once container for a read-only {@code Future}, allowing the underlying {@code Future} + * to be completed with a value or an exception. *

- * The underlying {@code Executor} is used to execute asynchronous handlers, e.g. via + * The associated {@code Executor} is used to run asynchronous handlers, for example, via * {@code promise.future().onComplete(...)}. * *

Creation

*

- * Promise offers static factory methods to create new promises which hasn't been fulfilled yet: + * {@code Promise} provides static factory methods to create new promises: *

    - *
  • create new promises: {@link Promise#make()}
  • + *
  • Unfulfilled promises: {@link Promise#make()}
  • + *
  • Already completed promises: + *
      + *
    • {@link #failed(Throwable)}
    • + *
    • {@link #fromTry(Try)}
    • + *
    • {@link #successful(Object)}
    • + *
    + *
  • *
- * And we may create new promises that are already finished: - *
    - *
  • {@link #failed(Throwable)}
  • - *
  • {@link #fromTry(Try)}
  • - *
  • {@link #successful(Object)}
  • - *
- * All the static factory methods mentioned above have additional versions which take an {@link Executor} as - * argument. This gives us more control over thread creation and thread pool sizes. + * All factory methods also have variants that accept an {@link Executor}, allowing finer control over + * thread usage and thread pool configuration. * *

One-shot API

*

- * The main purpose of a {@code Promise} is to complete its underlying {@code Future}. When only a single {@code Thread} - * will eventually complete the {@code Promise}, we use one of these methods. Calls will throw if the {@code Promise} is already - * completed. + * When a single {@code Thread} is responsible for completing the {@code Promise}, use one of the following methods. + * Calls will throw an exception if the {@code Promise} has already been completed: *

    - *
  • {@link #complete(Try)}
  • - *
  • {@link #completeWith(Future)}
  • - *
  • {@link #failure(Throwable)}
  • - *
  • {@link #success(Object)}
  • + *
  • {@link #complete(Try)}
  • + *
  • {@link #completeWith(Future)}
  • + *
  • {@link #failure(Throwable)}
  • + *
  • {@link #success(Object)}
  • *
* - *

API for competing threads

+ *

API for concurrent completion

*

- * When multiple {@code Thread}s may complete our {@code Promise}, we typically use one of these methods. Calls will - * gracefully return {@code false} if the {@code Promise} is already completed. + * When multiple {@code Thread}s may attempt to complete the {@code Promise}, use one of the following "try" methods. + * Calls will return {@code false} if the {@code Promise} is already completed: *

    - *
  • {@link #tryComplete(Try)}
  • - *
  • {@link #tryCompleteWith(Future)}
  • - *
  • {@link #tryFailure(Throwable)}
  • - *
  • {@link #trySuccess(Object)}
  • + *
  • {@link #tryComplete(Try)}
  • + *
  • {@link #tryCompleteWith(Future)}
  • + *
  • {@link #tryFailure(Throwable)}
  • + *
  • {@link #trySuccess(Object)}
  • *
* - * @param The result type of the underlying {@code Future}. + * @param the type of the value that completes the underlying {@code Future} * @author Daniel Dietrich */ public interface Promise { /** - * Creates a failed {@code Promise}, backed by the {@link Future#DEFAULT_EXECUTOR}. + * Creates a {@code Promise} that is already completed with a failure, using the + * {@link Future#DEFAULT_EXECUTOR} for asynchronous operations. * - * @param exception The reason why it failed. - * @param The value type of a successful result. - * @return A failed {@code Promise}. - * @throws NullPointerException if exception is null + * @param exception the cause of the failure + * @param the type of the value that would have been returned on success + * @return a {@code Promise} completed with the given failure + * @throws NullPointerException if {@code exception} is null */ static Promise failed(Throwable exception) { Objects.requireNonNull(exception, "exception is null"); @@ -90,13 +91,14 @@ static Promise failed(Throwable exception) { } /** - * Creates a failed {@code Promise}, backed by the given {@link Executor}. + * Creates a {@code Promise} that is already completed with a failure, using the specified {@link Executor} + * for asynchronous operations. * - * @param executor An {@code Executor} passed to the underlying {@link Future}. - * @param exception The reason why it failed. - * @param The value type of a successful result. - * @return A failed {@code Promise}. - * @throws NullPointerException if executor or exception is null + * @param executor the {@code Executor} used by the underlying {@link Future} + * @param exception the cause of the failure + * @param the type of the value that would have been returned on success + * @return a {@code Promise} completed with the given failure + * @throws NullPointerException if {@code executor} or {@code exception} is null */ static Promise failed(Executor executor, Throwable exception) { Objects.requireNonNull(executor, "executor is null"); @@ -105,25 +107,27 @@ static Promise failed(Executor executor, Throwable exception) { } /** - * Creates a {@code Promise} from a {@link Try}, backed by the {@link Future#DEFAULT_EXECUTOR}. + * Creates a {@code Promise} from the given {@link Try}, using the {@link Future#DEFAULT_EXECUTOR} + * for asynchronous operations. * - * @param result The result. - * @param The value type of a successful result. - * @return A completed {@code Promise} which contains either a {@code Success} or a {@code Failure}. - * @throws NullPointerException if result is null + * @param result the {@code Try} representing a success or failure + * @param the type of the value in case of success + * @return a {@code Promise} already completed with the given {@code Try} result + * @throws NullPointerException if {@code result} is null */ static Promise fromTry(Try result) { return fromTry(DEFAULT_EXECUTOR, result); } /** - * Creates a {@code Promise} from a {@link Try}, backed by the given {@link Executor}. + * Creates a {@code Promise} from the given {@link Try}, using the specified {@link Executor} + * for asynchronous operations. * - * @param executor An {@code Executor} passed to the underlying {@link Future}. - * @param result The result. - * @param The value type of a successful result. - * @return A completed {@code Promise} which contains either a {@code Success} or a {@code Failure}. - * @throws NullPointerException if executor or result is null + * @param executor the {@code Executor} used by the underlying {@link Future} + * @param result the {@code Try} representing a success or failure + * @param the type of the value in case of success + * @return a {@code Promise} already completed with the given {@code Try} result + * @throws NullPointerException if {@code executor} or {@code result} is null */ static Promise fromTry(Executor executor, Try result) { Objects.requireNonNull(executor, "executor is null"); @@ -132,23 +136,24 @@ static Promise fromTry(Executor executor, Try result) { } /** - * Makes a {@code Promise} that isn't fulfilled yet, backed by the {@link Future#DEFAULT_EXECUTOR}. - * {@link ForkJoinPool#commonPool()}. + * Creates a new {@code Promise} that is not yet completed, using the {@link Future#DEFAULT_EXECUTOR} + * (typically {@link ForkJoinPool#commonPool()}) for asynchronous operations. * - * @param Result type of the {@code Promise}. - * @return A new {@code Promise}. + * @param the type of the value that will complete the {@code Promise} + * @return a new, uncompleted {@code Promise} */ static Promise make() { return make(DEFAULT_EXECUTOR); } /** - * Makes a {@code Promise} that isn't fulfilled yet, backed by the given {@link Executor}. + * Creates a new {@code Promise} that is not yet completed, using the specified {@link Executor} + * for asynchronous operations. * - * @param executor An {@code Executor} passed to the underlying {@link Future}. - * @param Result type of the {@code Promise}. - * @return A new {@code Promise}. - * @throws NullPointerException if executor is null + * @param executor the {@code Executor} used by the underlying {@link Future} + * @param the type of the value that will complete the {@code Promise} + * @return a new, uncompleted {@code Promise} + * @throws NullPointerException if {@code executor} is null */ static Promise make(Executor executor) { Objects.requireNonNull(executor, "executor is null"); @@ -156,13 +161,12 @@ static Promise make(Executor executor) { } /** - * Narrows a widened {@code Promise} to {@code Promise} - * by performing a type-safe cast. This is eligible because immutable/read-only - * collections are covariant. + * Narrows a {@code Promise} to {@code Promise} through a type-safe cast. + * This is safe because immutable or read-only collections are covariant. * - * @param promise A {@code Promise}. - * @param Component type of the {@code Promise}. - * @return the given {@code promise} instance as narrowed type {@code Promise}. + * @param promise the {@code Promise} to narrow + * @param the component type of the {@code Promise} + * @return the same {@code promise} instance, cast to {@code Promise} */ @SuppressWarnings("unchecked") static Promise narrow(Promise promise) { @@ -170,24 +174,26 @@ static Promise narrow(Promise promise) { } /** - * Creates a succeeded {@code Promise}, backed by the {@link Future#DEFAULT_EXECUTOR}. + * Creates a {@code Promise} that is already completed successfully, using the + * {@link Future#DEFAULT_EXECUTOR} for asynchronous operations. * - * @param result The result. - * @param The value type of a successful result. - * @return A succeeded {@code Promise}. + * @param result the value of the successful result + * @param the type of the value + * @return a {@code Promise} already completed with the given result */ static Promise successful(T result) { return successful(DEFAULT_EXECUTOR, result); } /** - * Creates a succeeded {@code Promise}, backed by the given {@link Executor}. + * Creates a {@code Promise} that is already completed successfully, using the specified {@link Executor} + * for asynchronous operations. * - * @param executor An {@code Executor} passed to the underlying {@link Future}. - * @param result The result. - * @param The value type of a successful result. - * @return A succeeded {@code Promise}. - * @throws NullPointerException if executor is null + * @param executor the {@code Executor} used by the underlying {@link Future} + * @param result the value of the successful result + * @param the type of the value + * @return a {@code Promise} already completed with the given result + * @throws NullPointerException if {@code executor} is null */ static Promise successful(Executor executor, T result) { Objects.requireNonNull(executor, "executor is null"); @@ -197,7 +203,7 @@ static Promise successful(Executor executor, T result) { /** * Returns the {@link Executor} used by the underlying {@link Future} of this {@code Promise}. * - * @return The underlying {@code Executor}. + * @return the {@code Executor} associated with this {@code Promise} */ default Executor executor() { return executorService(); @@ -218,16 +224,16 @@ default Executor executor() { ExecutorService executorService(); /** - * Returns the underlying {@link Future} of this {@code Promise}. + * Returns the underlying {@link Future} associated with this {@code Promise}. * - * @return The {@code Future}. + * @return the underlying {@code Future} */ Future future(); /** - * Checks if this {@code Promise} is completed, i.e. has a value. + * Checks whether this {@code Promise} has been completed, either successfully or with a failure. * - * @return true, if the computation successfully finished or failed, false otherwise. + * @return {@code true} if the {@code Promise} is completed, {@code false} otherwise */ default boolean isCompleted() { return future().isCompleted(); @@ -236,9 +242,9 @@ default boolean isCompleted() { /** * Completes this {@code Promise} with the given {@code value}. * - * @param value Either a {@link Try.Success} containing the result or a {@link Try.Failure} containing an exception. - * @return This {@code Promise}. - * @throws IllegalStateException if this {@code Promise} has already been completed. + * @param value a {@link Try.Success} containing the result or a {@link Try.Failure} containing an exception + * @return this {@code Promise} + * @throws IllegalStateException if this {@code Promise} has already been completed */ default Promise complete(Try value) { if (tryComplete(value)) { @@ -249,29 +255,30 @@ default Promise complete(Try value) { } /** - * Attempts to completes this {@code Promise} with the given {@code value}. + * Attempts to complete this {@code Promise} with the given {@code value}. * - * @param value Either a {@link Try.Success} containing the result or a {@link Try.Failure} containing an exception. - * @return {@code false} if this {@code Promise} has already been completed, {@code true} otherwise. - * @throws IllegalStateException if this {@code Promise} has already been completed. + * @param value a {@link Try.Success} containing the result or a {@link Try.Failure} containing an exception + * @return {@code true} if the {@code Promise} was completed successfully, + * {@code false} if it was already completed */ boolean tryComplete(Try value); /** - * Completes this {@code Promise} with the given {@code Future}, once that {@code Future} is completed. + * Completes this {@code Promise} with the result of the given {@code Future} once it is completed. * - * @param other Another {@code Future} to react on. - * @return This {@code Promise}. + * @param other the {@code Future} whose result or failure will complete this {@code Promise} + * @return this {@code Promise} */ default Promise completeWith(Future other) { return tryCompleteWith(other); } /** - * Attempts to complete this {@code Promise} with the specified {@code Future}, once that {@code Future} is completed. + * Attempts to complete this {@code Promise} with the result of the given {@code Future} once it is completed. * - * @param other Another {@code Future} to react on. - * @return This {@code Promise}. + * @param other the {@code Future} whose result or failure may complete this {@code Promise} + * @return {@code true} if this {@code Promise} was completed by {@code other}, + * {@code false} if it was already completed */ default Promise tryCompleteWith(Future other) { other.onComplete(this::tryComplete); @@ -279,42 +286,44 @@ default Promise tryCompleteWith(Future other) { } /** - * Completes this {@code Promise} with the given {@code value}. + * Completes this {@code Promise} with the given value. * - * @param value A value. - * @return This {@code Promise}. - * @throws IllegalStateException if this {@code Promise} has already been completed. + * @param value the value to complete this {@code Promise} with + * @return this {@code Promise} + * @throws IllegalStateException if this {@code Promise} has already been completed */ default Promise success(T value) { return complete(Try.success(value)); } /** - * Completes this {@code Promise} with the given {@code value}. + * Attempts to complete this {@code Promise} with the given value. * - * @param value A value. - * @return {@code false} if this {@code Promise} has already been completed, {@code true} otherwise. + * @param value the value to complete this {@code Promise} with + * @return {@code true} if the {@code Promise} was completed successfully, + * {@code false} if it was already completed */ default boolean trySuccess(T value) { return tryComplete(Try.success(value)); } /** - * Completes this {@code Promise} with the given {@code exception}. + * Completes this {@code Promise} with the given exception. * - * @param exception An exception. - * @return This {@code Promise}. - * @throws IllegalStateException if this {@code Promise} has already been completed. + * @param exception the exception to complete this {@code Promise} with + * @return this {@code Promise} + * @throws IllegalStateException if this {@code Promise} has already been completed */ default Promise failure(Throwable exception) { return complete(Try.failure(exception)); } /** - * Completes this {@code Promise} with the given {@code exception}. + * Attempts to complete this {@code Promise} with the given exception. * - * @param exception An exception. - * @return {@code false} if this {@code Promise} has already been completed, {@code true} otherwise. + * @param exception the exception to complete this {@code Promise} with + * @return {@code true} if the {@code Promise} was completed successfully, + * {@code false} if it was already completed */ default boolean tryFailure(Throwable exception) { return tryComplete(Try.failure(exception)); diff --git a/vavr/src/main/java/io/vavr/control/Either.java b/vavr/src/main/java/io/vavr/control/Either.java index 6c58cfb37..79ee48d31 100644 --- a/vavr/src/main/java/io/vavr/control/Either.java +++ b/vavr/src/main/java/io/vavr/control/Either.java @@ -70,41 +70,37 @@ public interface Either extends Value, Serializable { long serialVersionUID = 1L; /** - * Constructs a {@link Right} + * Constructs a new {@link Right} instance containing the given value. * - * @param right The value. - * @param Type of left value. - * @param Type of right value. - * - * @return A new {@code Right} instance. + * @param right the value to store in the {@code Right} + * @param the type of the left value + * @param the type of the right value + * @return a new {@code Right} instance */ static Either right(R right) { return new Right<>(right); } /** - * Constructs a {@link Left} - * - * @param left The value. - * @param Type of left value. - * @param Type of right value. + * Constructs a new {@link Left} instance containing the given value. * - * @return A new {@code Left} instance. + * @param left the value to store in the {@code Left} + * @param the type of the left value + * @param the type of the right value + * @return a new {@code Left} instance */ static Either left(L left) { return new Left<>(left); } /** - * Narrows a widened {@code Either} to {@code Either} - * by performing a type-safe cast. This is eligible because immutable/read-only - * collections are covariant. - * - * @param either A {@code Either}. - * @param Type of left value. - * @param Type of right value. + * Narrows a {@code Either} to {@code Either} via a type-safe cast. + * This is safe because immutable or read-only collections are covariant. * - * @return the given {@code either} instance as narrowed type {@code Either}. + * @param either the {@code Either} to narrow + * @param the type of the left value + * @param the type of the right value + * @return the same {@code either} instance cast to {@code Either} */ @SuppressWarnings("unchecked") static Either narrow(Either either) { @@ -112,19 +108,19 @@ static Either narrow(Either either) { } /** - * Decides which {@code Either} to return, depending on the test value - - * if it's true, the result will be a {@link Either.Right}, - * if it's false - the result will be a {@link Either.Left} - * - * @param test A {@code boolean} value to evaluate - * @param right A {@code Supplier} supplier of right value, called if test is true - * @param left A {@code Supplier} supplier of left value, called if test is false - * @param Type of left value - * @param Type of right value - * - * @return {@code Either} with right or left value, depending on the test condition evaluation - * - * @throws NullPointerException if any of the arguments is null + * Returns an {@code Either} based on the given test condition. + *
    + *
  • If {@code test} is {@code true}, the result is a {@link Either.Right} created from {@code right}.
  • + *
  • If {@code test} is {@code false}, the result is a {@link Either.Left} created from {@code left}.
  • + *
+ * + * @param test the boolean condition to evaluate + * @param right a {@code Supplier} providing the right value if {@code test} is true + * @param left a {@code Supplier} providing the left value if {@code test} is false + * @param the type of the left value + * @param the type of the right value + * @return an {@code Either} containing the left or right value depending on {@code test} + * @throws NullPointerException if any argument is null */ static Either cond(boolean test, Supplier right, Supplier left) { Objects.requireNonNull(right, "right is null"); @@ -134,19 +130,19 @@ static Either cond(boolean test, Supplier right, Suppl } /** - * Decides which {@code Either} to return, depending on the test value - - * if it's true, the result will be a {@link Either.Right}, - * if it's false - the result will be a {@link Either.Left} - * - * @param test A {@code boolean} value to evaluate - * @param right A n{@code R} right value, returned if test is true - * @param left A {@code L} left value, returned if test is false - * @param Type of left value - * @param Type of right value - * - * @return {@code Either} with right or left value, depending on the test condition evaluation - * - * @throws NullPointerException if any of the arguments is null + * Returns an {@code Either} based on the given test condition. + *
    + *
  • If {@code test} is {@code true}, the result is a {@link Either.Right} containing {@code right}.
  • + *
  • If {@code test} is {@code false}, the result is a {@link Either.Left} containing {@code left}.
  • + *
+ * + * @param test the boolean condition to evaluate + * @param right the {@code R} value to return if {@code test} is true + * @param left the {@code L} value to return if {@code test} is false + * @param the type of the left value + * @param the type of the right value + * @return an {@code Either} containing either the left or right value depending on {@code test} + * @throws NullPointerException if any argument is null */ static Either cond(boolean test, R right, L left) { Objects.requireNonNull(right, "right is null"); @@ -156,25 +152,24 @@ static Either cond(boolean test, R right, L left) { } /** - * Returns the left value. + * Returns the left value of this {@code Either}. * - * @return The left value. - * - * @throws NoSuchElementException if this is a {@code Right}. + * @return the left value + * @throws NoSuchElementException if this {@code Either} is a {@link Either.Right} */ L getLeft(); /** - * Returns whether this Either is a Left. + * Checks whether this {@code Either} is a {@link Either.Left}. * - * @return true, if this is a Left, false otherwise + * @return {@code true} if this is a {@code Left}, {@code false} otherwise */ boolean isLeft(); /** - * Returns whether this Either is a Right. + * Checks whether this {@code Either} is a {@link Either.Right}. * - * @return true, if this is a Right, false otherwise + * @return {@code true} if this is a {@code Right}, {@code false} otherwise */ boolean isRight(); @@ -203,14 +198,17 @@ default RightProjection right() { } /** - * Maps either the left or the right side of this disjunction. - * - * @param leftMapper maps the left value if this is a Left - * @param rightMapper maps the right value if this is a Right - * @param The new left type of the resulting Either - * @param The new right type of the resulting Either - * - * @return A new Either instance + * Transforms the value of this {@code Either} by applying one of the given mapping functions. + *
    + *
  • If this is a {@link Either.Left}, {@code leftMapper} is applied to the left value.
  • + *
  • If this is a {@link Either.Right}, {@code rightMapper} is applied to the right value.
  • + *
+ * + * @param leftMapper function to transform the left value if this is a {@code Left} + * @param rightMapper function to transform the right value if this is a {@code Right} + * @param the type of the left value in the resulting {@code Either} + * @param the type of the right value in the resulting {@code Either} + * @return a new {@code Either} instance with the transformed value */ default Either bimap(Function leftMapper, Function rightMapper) { Objects.requireNonNull(leftMapper, "leftMapper is null"); @@ -223,13 +221,16 @@ default Either bimap(Function leftMapper, F } /** - * Folds either the left or the right side of this disjunction. - * - * @param leftMapper maps the left value if this is a Left - * @param rightMapper maps the right value if this is a Right - * @param type of the folded value - * - * @return A value of type U + * Reduces this {@code Either} to a single value by applying one of the given functions. + *
    + *
  • If this is a {@link Either.Left}, {@code leftMapper} is applied to the left value.
  • + *
  • If this is a {@link Either.Right}, {@code rightMapper} is applied to the right value.
  • + *
+ * + * @param leftMapper function to transform the left value if this is a {@code Left} + * @param rightMapper function to transform the right value if this is a {@code Right} + * @param the type of the resulting value + * @return a value of type {@code U} obtained by applying the appropriate function */ default U fold(Function leftMapper, Function rightMapper) { Objects.requireNonNull(leftMapper, "leftMapper is null"); @@ -242,14 +243,13 @@ default U fold(Function leftMapper, Function>} into a {@code Either, Seq>}. + * Transforms an {@link Iterable} of {@code Either} into a single {@code Either, Seq>}. *

- * If any of the given {@code Either}s is a {@link Either.Left} then {@code sequence} returns a - * {@link Either.Left} containing a non-empty {@link Seq} of all left values. + * If any of the given {@code Either}s is a {@link Either.Left}, the result is a {@link Either.Left} + * containing a non-empty {@link Seq} of all left values. *

- * If none of the given {@code Either}s is a {@link Either.Left} then {@code sequence} returns a - * {@link Either.Right} containing a (possibly empty) {@link Seq} of all right values. + * If all of the given {@code Either}s are {@link Either.Right}, the result is a {@link Either.Right} + * containing a (possibly empty) {@link Seq} of all right values. * *

{@code
      * // = Right(Seq())
@@ -262,12 +262,11 @@ default  U fold(Function leftMapper, Function
      *
-     * @param eithers An {@link Iterable} of {@code Either}s
-     * @param      closure of all left types of the given {@code Either}s
-     * @param      closure of all right types of the given {@code Either}s
-     *
-     * @return An {@code Either} of a {@link Seq} of left or right values
-     *
+     * @param eithers an {@link Iterable} of {@code Either} instances
+     * @param      the common type of left values
+     * @param      the common type of right values
+     * @return an {@code Either} containing a {@link Seq} of left values if any {@code Either} was a {@link Either.Left}, 
+     *         otherwise a {@link Seq} of right values
      * @throws NullPointerException if {@code eithers} is null
      */
     @SuppressWarnings("unchecked")
@@ -282,18 +281,20 @@ static  Either, Seq> sequence(Iterable} into a {@code Either>}.
-     *
-     * @param values An {@code Iterable} of values.
-     * @param mapper A mapper of values to Eithers
-     * @param     The mapped left value type.
-     * @param     The mapped right value type.
-     * @param     The type of the given values.
-     *
-     * @return A {@code Either} of a {@link Seq} of results.
-     *
-     * @throws NullPointerException if values or f is null.
+     * Transforms an {@link Iterable} of values into a single {@code Either, Seq>} by applying a mapping function 
+     * that returns an {@code Either} for each value.
+     * 

+ * If the mapper returns any {@link Either.Left}, the resulting {@code Either} is a {@link Either.Left} + * containing a {@link Seq} of all left values. Otherwise, the result is a {@link Either.Right} containing + * a {@link Seq} of all right values. + * + * @param values an {@code Iterable} of values to map + * @param mapper a function mapping each value to an {@code Either} + * @param the type of left values + * @param the type of right values + * @param the type of the input values + * @return a single {@code Either} containing a {@link Seq} of left or right results + * @throws NullPointerException if {@code values} or {@code mapper} is null */ static Either, Seq> traverse(Iterable values, Function> mapper) { Objects.requireNonNull(values, "values is null"); @@ -302,14 +303,13 @@ static Either, Seq> traverse(Iterable values, F } /** - * Reduces many {@code Either}s into a single {@code Either} by transforming an - * {@code Iterable>} into a {@code Either>}. + * Transforms an {@link Iterable} of {@code Either} into a single {@code Either>}. *

- * If any of the given {@code Either}s is a {@link Either.Left} then {@code sequenceRight} returns a - * {@link Either.Left} containing the first left value (in iteration order). + * If any of the given {@code Either}s is a {@link Either.Left}, the result is a {@link Either.Left} + * containing the first left value encountered in iteration order. *

- * If none of the given {@code Either}s is a {@link Either.Left} then {@code sequenceRight} returns a - * {@link Either.Right} containing a (possibly empty) {@link Seq} of all right values. + * If all of the given {@code Either}s are {@link Either.Right}, the result is a {@link Either.Right} + * containing a (possibly empty) {@link Seq} of all right values. * *

{@code
      * // = Right(Seq())
@@ -322,12 +322,10 @@ static  Either, Seq> traverse(Iterable values, F
      * Either.sequenceRight(List.of(Either.right(1), Either.left("x1"), Either.left("x2")))
      * }
* - * @param eithers An {@link Iterable} of {@code Either}s - * @param closure of all left types of the given {@code Either}s - * @param closure of all right types of the given {@code Either}s - * - * @return An {@code Either} of either a {@link Seq} of right values or the first left value, if present. - * + * @param eithers an {@link Iterable} of {@code Either} instances + * @param the type of left values + * @param the type of right values + * @return an {@code Either} containing either the first left value if present, or a {@link Seq} of all right values * @throws NullPointerException if {@code eithers} is null */ static Either> sequenceRight(Iterable> eithers) { @@ -344,18 +342,20 @@ static Either> sequenceRight(Iterable} into a {@code Either>}. - * - * @param values An {@code Iterable} of values. - * @param mapper A mapper of values to Eithers - * @param The mapped left value type. - * @param The mapped right value type. - * @param The type of the given values. - * - * @return A {@code Either} of a {@link Seq} of results. - * - * @throws NullPointerException if values or f is null. + * Transforms an {@link Iterable} of values into a single {@code Either, Seq>} by applying a mapping + * function that returns an {@code Either} for each element. + *

+ * If the mapper returns any {@link Either.Left}, the resulting {@code Either} is a {@link Either.Left} + * containing a {@link Seq} of all left values. Otherwise, the result is a {@link Either.Right} containing + * a {@link Seq} of all right values. + * + * @param values an {@code Iterable} of values to map + * @param mapper a function mapping each value to an {@code Either} + * @param the type of left values + * @param the type of right values + * @param the type of input values + * @return a single {@code Either} containing a {@link Seq} of left or right results + * @throws NullPointerException if {@code values} or {@code mapper} is null */ static Either> traverseRight(Iterable values, Function> mapper) { Objects.requireNonNull(values, "values is null"); @@ -364,12 +364,10 @@ static Either> traverseRight(Iterable values, F } /** - * Gets the Right value or an alternate value, if the projected Either is a Left. - * - * @param other a function which converts a Left value to an alternative Right value + * Returns the right value of this {@code Either}, or an alternative value if this is a {@link Either.Left}. * - * @return the right value, if the underlying Either is a Right or else the alternative Right value provided by - * {@code other} by applying the Left value. + * @param other a function that converts a left value to an alternative right value + * @return the right value if present, otherwise the alternative value produced by applying {@code other} to the left value */ default R getOrElseGet(Function other) { Objects.requireNonNull(other, "other is null"); @@ -381,9 +379,9 @@ default R getOrElseGet(Function other) { } /** - * Runs an action in the case this is a projection on a Left value. + * Executes the given action if this projection represents a {@link Either.Left} value. * - * @param action an action which consumes a Left value + * @param action a consumer that processes the left value */ default void orElseRun(Consumer action) { Objects.requireNonNull(action, "action is null"); @@ -393,15 +391,12 @@ default void orElseRun(Consumer action) { } /** - * Gets the Right value or throws, if the projected Either is a Left. + * Returns the right value of this {@code Either}, or throws an exception if it is a {@link Either.Left}. * - * @param a throwable type - * @param exceptionFunction a function which creates an exception based on a Left value - * - * @return the right value, if the underlying Either is a Right or else throws the exception provided by - * {@code exceptionFunction} by applying the Left value. - * - * @throws X if the projected Either is a Left + * @param the type of exception to be thrown + * @param exceptionFunction a function that produces an exception from the left value + * @return the right value if present + * @throws X if this {@code Either} is a {@link Either.Left}, using the exception produced by {@code exceptionFunction} */ default R getOrElseThrow(Function exceptionFunction) throws X { Objects.requireNonNull(exceptionFunction, "exceptionFunction is null"); @@ -413,9 +408,10 @@ default R getOrElseThrow(Function exceptionF } /** - * Converts a {@code Left} to a {@code Right} vice versa by wrapping the value in a new type. + * Swaps the sides of this {@code Either}, converting a {@link Either.Left} to a {@link Either.Right} + * and vice versa. * - * @return a new {@code Either} + * @return a new {@code Either} with the left and right values swapped */ default Either swap() { if (isRight()) { @@ -428,13 +424,14 @@ default Either swap() { // -- Adjusted return types of Monad methods /** - * FlatMaps this right-biased Either. - * - * @param mapper A mapper - * @param Component type of the mapped right value - * - * @return this as {@code Either} if this is a Left, otherwise the right mapping result + * Applies a flat-mapping function to the right value of this right-biased {@code Either}. + *

+ * If this {@code Either} is a {@link Either.Left}, it is returned unchanged. + * Otherwise, the {@code mapper} function is applied to the right value, and its result is returned. * + * @param mapper a function that maps the right value to another {@code Either} + * @param the type of the right value in the resulting {@code Either} + * @return this {@code Either} unchanged if it is a {@link Either.Left}, or the result of applying {@code mapper} if it is a {@link Either.Right} * @throws NullPointerException if {@code mapper} is null */ @SuppressWarnings("unchecked") @@ -448,7 +445,9 @@ default Either flatMap(Function + * If this {@code Either} is a {@link Either.Left}, no operation is performed and it is returned unchanged. * *


      * import static io.vavr.API.*;
@@ -460,11 +459,9 @@ default  Either flatMap(Function
* - * @param mapper A mapper - * @param Component type of the mapped right value - * - * @return a mapped {@code Monad} - * + * @param mapper a function to transform the right value + * @param the type of the right value in the resulting {@code Either} + * @return a new {@code Either} with the right value transformed, or the original left value * @throws NullPointerException if {@code mapper} is null */ @SuppressWarnings("unchecked") @@ -479,7 +476,9 @@ default Either map(Function mapper) { } /** - * Maps the value of this Either if it is a Left, performs no operation if this is a Right. + * Transforms the left value of this {@code Either} using the given mapping function. + *

+ * If this {@code Either} is a {@link Either.Right}, no operation is performed and it is returned unchanged. * *

{@code
      * import static io.vavr.API.*;
@@ -491,12 +490,10 @@ default  Either map(Function mapper) {
      * Right("a").mapLeft(i -> i + 1);
      * }
* - * @param leftMapper A mapper - * @param Component type of the mapped right value - * - * @return a mapped {@code Monad} - * - * @throws NullPointerException if {@code mapper} is null + * @param leftMapper a function to transform the left value + * @param the type of the left value in the resulting {@code Either} + * @return a new {@code Either} with the left value transformed, or the original right value + * @throws NullPointerException if {@code leftMapper} is null */ @SuppressWarnings("unchecked") default Either mapLeft(Function leftMapper) { @@ -511,12 +508,13 @@ default Either mapLeft(Function leftMapper) { // -- Adjusted return types of Value methods /** - * Filters this right-biased {@code Either} by testing a predicate. - * - * @param predicate A predicate - * - * @return a new {@code Option} instance + * Returns an {@link Option} describing the right value of this right-biased {@code Either} + * if it satisfies the given predicate. + *

+ * If this {@code Either} is a {@link Either.Left} or the predicate does not match, {@link Option#none()} is returned. * + * @param predicate a predicate to test the right value + * @return an {@link Option} containing the right value if it satisfies the predicate, or {@link Option#none()} otherwise * @throws NullPointerException if {@code predicate} is null */ default Option> filter(Predicate predicate) { @@ -525,10 +523,11 @@ default Option> filter(Predicate predicate) { } /** - * Filters this right-biased {@code Either} by testing a predicate. - * If the {@code Either} is a {@code Right} and the predicate doesn't match, the - * {@code Either} will be turned into a {@code Left} with contents computed by applying - * the zero function to the {@code Either} value. + * Filters this right-biased {@code Either} using the given predicate. + *

+ * If this {@code Either} is a {@link Either.Right} and the predicate evaluates to {@code false}, + * the result is a {@link Either.Left} obtained by applying the {@code zero} function to the right value. + * If the predicate evaluates to {@code true}, the {@code Either.Right} is returned unchanged. * *

{@code
      * import static io.vavr.API.*;
@@ -540,12 +539,10 @@ default Option> filter(Predicate predicate) {
      * Right("a").filterOrElse(i -> true, val -> "bad: " + val);
      * }
* - * @param predicate A predicate - * @param zero A function that turns a right value into a left value if the right value does not make it through the filter. - * - * @return an {@code Either} instance - * - * @throws NullPointerException if {@code predicate} is null + * @param predicate a predicate to test the right value + * @param zero a function that converts a right value to a left value if the predicate fails + * @return an {@code Either} containing the right value if the predicate matches, or a left value otherwise + * @throws NullPointerException if {@code predicate} or {@code zero} is null */ default Either filterOrElse(Predicate predicate, Function zero) { Objects.requireNonNull(predicate, "predicate is null"); @@ -558,11 +555,10 @@ default Either filterOrElse(Predicate predicate, Function orElse(Supplier> } /** - * A right-biased {@code Either}'s value is computed synchronously. + * Indicates that a right-biased {@code Either} computes its value synchronously. * - * @return false + * @return {@code false} */ @Override default boolean isAsync() { @@ -595,9 +591,9 @@ default boolean isAsync() { } /** - * A right-biased {@code Either}'s value is computed eagerly. + * Indicates that a right-biased {@code Either} computes its value eagerly. * - * @return false + * @return {@code false} */ @Override default boolean isLazy() { @@ -605,7 +601,7 @@ default boolean isLazy() { } /** - * A right-biased {@code Either} is single-valued. + * Indicates that a right-biased {@code Either} contains exactly one value. * * @return {@code true} */ diff --git a/vavr/src/main/java/io/vavr/control/Option.java b/vavr/src/main/java/io/vavr/control/Option.java index 3b6e27d27..a23775eed 100644 --- a/vavr/src/main/java/io/vavr/control/Option.java +++ b/vavr/src/main/java/io/vavr/control/Option.java @@ -34,42 +34,42 @@ import java.util.function.Supplier; /** - * Replacement for {@link java.util.Optional}. + * A replacement for {@link java.util.Optional}. *

- * Option is a monadic container type which - * represents an optional value. Instances of Option are either an instance of {@link Some} or the - * singleton {@link None}. + * {@code Option} is a monadic container type representing the presence or absence of a value. + * An instance is either a {@link Some} holding a value or the singleton {@link None}. *

- * Most of the API is taken from {@link java.util.Optional}. A similar type can be found in Haskell and Scala. + * The design is similar to {@link java.util.Optional} and related types in + * Haskell and + * Scala. * - * @param The type of the optional value. - * @author Daniel Dietrich + * @param the type of the optional value */ public interface Option extends Value, Serializable { long serialVersionUID = 1L; /** - * Creates a new {@code Option} of a given value. + * Creates an {@code Option} from the given value. * - * @param value A value - * @param type of the value - * @return {@code Some(value)} if value is not {@code null}, {@code None} otherwise + * @param value the value to wrap + * @param the value type + * @return {@code Some(value)} if the value is non-null, otherwise {@code None} */ static Option of(T value) { return (value == null) ? none() : some(value); } /** - * Reduces many {@code Option}s into a single {@code Option} by transforming an - * {@code Iterable>} into a {@code Option>}. If any of - * the Options are {@link Option.None}, then this returns {@link Option.None}. + * Reduces multiple {@code Option} values into a single {@code Option} by transforming + * an {@code Iterable>} into an {@code Option>}. + *

+ * If any element is {@link Option.None}, the result is {@code None}. + * Otherwise, all contained values are collected into a {@link Seq} wrapped in {@code Some}. * - * @param values An {@code Iterable} of {@code Option}s - * @param type of the Options - * @return An {@code Option} of a {@link Seq} of results + * @param values an iterable of {@code Option} values + * @param the element type + * @return an {@code Option} containing a {@code Seq} of all values, or {@code None} if any value is empty * @throws NullPointerException if {@code values} is null */ static Option> sequence(Iterable> values) { @@ -85,15 +85,19 @@ static Option> sequence(Iterable> value } /** - * Maps the values of an iterable to a sequence of mapped values into a single {@code Option} by - * transforming an {@code Iterable} into a {@code Option>}. - * - * @param values An {@code Iterable} of values. - * @param mapper A mapper of values to Options - * @param The type of the given values. - * @param The mapped value type. - * @return A {@code Option} of a {@link Seq} of results. - * @throws NullPointerException if values or f is null. + * Maps the elements of an iterable into {@code Option} values and collects the results + * into a single {@code Option}. + *

+ * Each element is transformed using {@code mapper}. + * If any mapped value is {@link Option.None}, the result is {@code None}. + * Otherwise, all mapped values are accumulated into a {@link Seq} wrapped in {@code Some}. + * + * @param values an iterable of input values + * @param mapper a function mapping each value to an {@code Option} + * @param the input element type + * @param the mapped element type + * @return an {@code Option} containing a {@code Seq} of mapped values, or {@code None} if any mapping yields {@code None} + * @throws NullPointerException if {@code values} or {@code mapper} is null */ static Option> traverse(Iterable values, Function> mapper) { Objects.requireNonNull(values, "values is null"); @@ -102,29 +106,27 @@ static Option> traverse(Iterable values, Function - * The only difference to {@link Option#of(Object)} is, when called with argument {@code null}. + * Unlike {@link Option#of(Object)}, this method preserves {@code null}: *

-     * 
-     * Option.of(null);   // = None
-     * Option.some(null); // = Some(null)
-     * 
+     * Option.of(null);   // yields None
+     * Option.some(null); // yields Some(null)
      * 
* - * @param value A value - * @param type of the value - * @return {@code Some(value)} + * @param value the value to wrap, possibly {@code null} + * @param the value type + * @return a {@code Some} containing {@code value} */ static Option some(T value) { return new Some<>(value); } /** - * Returns the single instance of {@code None} + * Returns the singleton {@code None} instance. * - * @param component type - * @return the single instance of {@code None} + * @param the option's component type + * @return the singleton {@code None} */ static Option none() { @SuppressWarnings("unchecked") @@ -133,13 +135,13 @@ static Option none() { } /** - * Narrows a widened {@code Option} to {@code Option} - * by performing a type-safe cast. This is eligible because immutable/read-only - * collections are covariant. + * Narrows a widened {@code Option} to {@code Option} via a type-safe cast. + *

+ * This is safe because immutable/read-only types are covariant. * - * @param option A {@code Option}. - * @param Component type of the {@code Option}. - * @return the given {@code option} instance as narrowed type {@code Option}. + * @param option the {@code Option} to narrow + * @param the component type of the {@code Option} + * @return the same {@code Option} instance, cast to {@code Option} */ @SuppressWarnings("unchecked") static Option narrow(Option option) { @@ -147,13 +149,14 @@ static Option narrow(Option option) { } /** - * Creates {@code Some} of suppliers value if condition is true, or {@code None} in other case - * - * @param type of the optional value - * @param condition A boolean value - * @param supplier An optional value supplier, may supply {@code null} - * @return return {@code Some} of supplier's value if condition is true, or {@code None} in other case - * @throws NullPointerException if the given {@code supplier} is null + * Returns {@code Some} of the value supplied by {@code supplier} if {@code condition} is true, + * or {@code None} if {@code condition} is false. + * + * @param the type of the optional value + * @param condition the condition to test + * @param supplier a supplier of the value, may return {@code null} + * @return {@code Some} of the supplied value if {@code condition} is true, otherwise {@code None} + * @throws NullPointerException if {@code supplier} is null */ static Option when(boolean condition, Supplier supplier) { Objects.requireNonNull(supplier, "supplier is null"); @@ -161,23 +164,23 @@ static Option when(boolean condition, Supplier supplier) { } /** - * Creates {@code Some} of value if condition is true, or {@code None} in other case + * Returns {@code Some} of the given {@code value} if {@code condition} is true, or {@code None} otherwise. * - * @param type of the optional value - * @param condition A boolean value - * @param value An optional value, may be {@code null} - * @return return {@code Some} of value if condition is true, or {@code None} in other case + * @param the type of the optional value + * @param condition the condition to test + * @param value the value to wrap, may be {@code null} + * @return {@code Some} of {@code value} if {@code condition} is true, otherwise {@code None} */ static Option when(boolean condition, T value) { return condition ? some(value) : none(); } /** - * Wraps a Java Optional to a new Option + * Wraps a {@link java.util.Optional} in a new {@code Option}. * - * @param optional a given optional to wrap in {@code Option} - * @param type of the value - * @return {@code Some(optional.get())} if value is Java {@code Optional} is present, {@code None} otherwise + * @param optional the Java {@code Optional} to wrap + * @param the type of the contained value + * @return {@code Some(optional.get())} if the {@code Optional} is present, otherwise {@code None} */ @SuppressWarnings("OptionalUsedAsFieldOrParameterType") static Option ofOptional(Optional optional) { @@ -186,22 +189,21 @@ static Option ofOptional(Optional optional) { } /** - * Collects value that is in the domain of the given {@code partialFunction} by mapping the value to type {@code R}. - * - *

{@code
-     * partialFunction.isDefinedAt(value)
-     * }
- * - * If the element makes it through that filter, the mapped instance is wrapped in {@code Option} + * Applies a {@code partialFunction} to the value of this {@code Option} if it is defined for that value, + * and wraps the result in a new {@code Option}. + *

+ * If the {@code partialFunction} is not defined for the value, {@code None} is returned. * *

{@code
-     * R newValue = partialFunction.apply(value)
+     * if (partialFunction.isDefinedAt(value)) {
+     *     R newValue = partialFunction.apply(value);
+     *     // wrapped in Some(newValue)
+     * }
      * }
* - * - * @param partialFunction A function that is not necessarily defined on value of this option. - * @param The new value type - * @return A new {@code Option} instance containing value of type {@code R} + * @param partialFunction a function that may not be defined for all input values + * @param the type of the mapped value + * @return a new {@code Option} containing the mapped value if defined, otherwise {@code None} * @throws NullPointerException if {@code partialFunction} is null */ default Option collect(PartialFunction partialFunction) { @@ -210,17 +212,17 @@ default Option collect(PartialFunction partialFun } /** - * Returns true, if this is {@code None}, otherwise false, if this is {@code Some}. + * Checks whether this {@code Option} is empty. * - * @return true, if this {@code Option} is empty, false otherwise + * @return {@code true} if this is {@code None}, {@code false} if this is {@code Some} */ @Override boolean isEmpty(); /** - * Runs a Java Runnable passed as parameter if this {@code Option} is empty. + * Executes the given {@link Runnable} if this {@code Option} is empty ({@code None}). * - * @param action a given Runnable to be run + * @param action a {@code Runnable} to execute * @return this {@code Option} */ default Option onEmpty(Runnable action) { @@ -232,9 +234,9 @@ default Option onEmpty(Runnable action) { } /** - * An {@code Option}'s value is computed synchronously. + * Indicates that an {@code Option}'s value is computed synchronously. * - * @return false + * @return {@code false} */ @Override default boolean isAsync() { @@ -242,20 +244,20 @@ default boolean isAsync() { } /** - * Returns true, if this is {@code Some}, otherwise false, if this is {@code None}. + * Checks whether this {@code Option} contains a value. *

- * Please note that it is possible to create {@code new Some(null)}, which is defined. + * Note that {@code Some(null)} is considered defined. * - * @return true, if this {@code Option} has a defined value, false otherwise + * @return {@code true} if this is {@code Some}, {@code false} if this is {@code None} */ default boolean isDefined() { return !isEmpty(); } /** - * An {@code Option}'s value is computed eagerly. + * Indicates that an {@code Option}'s value is computed eagerly. * - * @return false + * @return {@code false} */ @Override default boolean isLazy() { @@ -263,7 +265,7 @@ default boolean isLazy() { } /** - * An {@code Option} is single-valued. + * Indicates that an {@code Option} contains exactly one value. * * @return {@code true} */ @@ -273,21 +275,21 @@ default boolean isSingleValued() { } /** - * Gets the value if this is a {@code Some} or throws if this is a {@code None}. + * Returns the value contained in this {@code Some}, or throws if this is {@code None}. * - * @return the value - * @throws NoSuchElementException if this is a {@code None}. + * @return the contained value + * @throws NoSuchElementException if this is {@code None} */ @Override T get(); /** - * Returns the value if this is a {@code Some} or the {@code other} value if this is a {@code None}. + * Returns the value contained in this {@code Some}, or the provided {@code other} value if this is {@code None}. *

- * Please note, that the other value is eagerly evaluated. + * Note that {@code other} is evaluated eagerly. * - * @param other An alternative value - * @return This value, if this Option is defined or the {@code other} value, if this Option is empty. + * @param other an alternative value to return if this is {@code None} + * @return the contained value if defined, otherwise {@code other} */ @Override default T getOrElse(T other) { @@ -295,10 +297,10 @@ default T getOrElse(T other) { } /** - * Returns this {@code Option} if it is nonempty, otherwise return the alternative. + * Returns this {@code Option} if it is non-empty, otherwise returns the provided alternative {@code Option}. * - * @param other An alternative {@code Option} - * @return this {@code Option} if it is nonempty, otherwise return the alternative. + * @param other an alternative {@code Option} to return if this is {@code None} + * @return this {@code Option} if defined, otherwise {@code other} */ @SuppressWarnings("unchecked") default Option orElse(Option other) { @@ -307,10 +309,11 @@ default Option orElse(Option other) { } /** - * Returns this {@code Option} if it is nonempty, otherwise return the result of evaluating supplier. + * Returns this {@code Option} if it is non-empty; otherwise, returns the {@code Option} provided by the supplier. * - * @param supplier An alternative {@code Option} supplier - * @return this {@code Option} if it is nonempty, otherwise return the result of evaluating supplier. + * @param supplier a supplier of an alternative {@code Option} if this is {@code None} + * @return this {@code Option} if defined, otherwise the result of {@code supplier.get()} + * @throws NullPointerException if {@code supplier} is null */ @SuppressWarnings("unchecked") default Option orElse(Supplier> supplier) { @@ -319,13 +322,13 @@ default Option orElse(Supplier> supplier) { } /** - * Returns the value if this is a {@code Some}, otherwise the {@code other} value is returned, - * if this is a {@code None}. + * Returns the value contained in this {@code Some}, or the value supplied by {@code supplier} if this is {@code None}. *

- * Please note, that the other value is lazily evaluated. + * The alternative value is evaluated lazily. * - * @param supplier An alternative value supplier - * @return This value, if this Option is defined or the {@code other} value, if this Option is empty. + * @param supplier a supplier of an alternative value if this is {@code None} + * @return the contained value if defined, otherwise the value returned by {@code supplier} + * @throws NullPointerException if {@code supplier} is null */ @Override default T getOrElse(Supplier supplier) { @@ -334,12 +337,13 @@ default T getOrElse(Supplier supplier) { } /** - * Returns the value if this is a {@code Some}, otherwise throws an exception. + * Returns the value contained in this {@code Some}, or throws an exception provided by {@code exceptionSupplier} if this is {@code None}. * - * @param exceptionSupplier An exception supplier - * @param A throwable - * @return This value, if this Option is defined, otherwise throws X - * @throws X a throwable + * @param exceptionSupplier a supplier of the exception to throw if this is {@code None} + * @param the type of the exception + * @return the contained value if defined + * @throws X if this {@code Option} is {@code None} + * @throws NullPointerException if {@code exceptionSupplier} is null */ @Override default T getOrElseThrow(Supplier exceptionSupplier) throws X { @@ -352,11 +356,12 @@ default T getOrElseThrow(Supplier exceptionSupplier) th } /** - * Returns {@code Some(value)} if this is a {@code Some} and the value satisfies the given predicate. - * Otherwise {@code None} is returned. + * Returns {@code Some(value)} if this {@code Option} is a {@code Some} and the contained value satisfies the given predicate. + * Otherwise, returns {@code None}. * - * @param predicate A predicate which is used to test an optional value - * @return {@code Some(value)} or {@code None} as specified + * @param predicate a predicate to test the contained value + * @return {@code Some(value)} if the value satisfies the predicate, otherwise {@code None} + * @throws NullPointerException if {@code predicate} is null */ default Option filter(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); @@ -364,11 +369,13 @@ default Option filter(Predicate predicate) { } /** - * Maps the value to a new {@code Option} if this is a {@code Some}, otherwise returns {@code None}. + * Transforms the value of this {@code Option} using the given mapper if it is a {@code Some}. + * Returns {@code None} if this is {@code None}. * - * @param mapper A mapper - * @param Component type of the resulting Option - * @return a new {@code Option} + * @param mapper a function to transform the contained value + * @param the type of the resulting {@code Option}'s value + * @return a new {@code Option} containing the mapped value, or {@code None} + * @throws NullPointerException if {@code mapper} is null */ @SuppressWarnings("unchecked") default Option flatMap(Function> mapper) { @@ -377,11 +384,13 @@ default Option flatMap(Function> } /** - * Maps the value and wraps it in a new {@code Some} if this is a {@code Some}, returns {@code None}. + * Transforms the value of this {@code Some} using the given mapper and wraps it in a new {@code Some}. + * Returns {@code None} if this is {@code None}. * - * @param mapper A value mapper - * @param The new value type - * @return a new {@code Some} containing the mapped value if this Option is defined, otherwise {@code None}, if this is empty. + * @param mapper a function to transform the contained value + * @param the type of the resulting {@code Some}'s value + * @return a new {@code Some} with the mapped value if this is defined, otherwise {@code None} + * @throws NullPointerException if {@code mapper} is null */ @Override default Option map(Function mapper) { @@ -400,12 +409,12 @@ default Option mapToVoid() { } /** - * Converts this to a {@link Try}, then runs the given checked function if this is a {@link Try.Success}, - * passing the result of the current expression to it. + * Converts this {@code Option} to a {@link Try}, then applies the given checked function if this is a {@link Try.Success}, + * passing the contained value to it. * - * @param The new component type - * @param mapper A checked function - * @return a {@code Try} + * @param the type of the resulting {@code Try}'s value + * @param mapper a checked function to transform the contained value + * @return a {@code Try} containing the mapped value if this {@code Option} is defined, otherwise a {@link Try.Failure} * @throws NullPointerException if {@code mapper} is null */ default Try mapTry(CheckedFunction1 mapper) { @@ -413,22 +422,29 @@ default Try mapTry(CheckedFunction1 mapper) { } /** - * Folds either the {@code None} or the {@code Some} side of the Option value. - * - * @param ifNone maps the left value if this is a None - * @param f maps the value if this is a Some - * @param type of the folded value - * @return A value of type U + * Folds this {@code Option} into a single value by applying one of two functions: + *

    + *
  • {@code ifNone} is applied if this is {@code None}
  • + *
  • {@code f} is applied to the contained value if this is {@code Some}
  • + *
+ * + * @param ifNone a function to produce a value if this is {@code None} + * @param f a function to transform the contained value if this is {@code Some} + * @param the type of the folded result + * @return the result of applying {@code f} or {@code ifNone} depending on whether this is {@code Some} or {@code None} + * @throws NullPointerException if {@code ifNone} or {@code f} is null */ default U fold(Supplier ifNone, Function f) { return this.map(f).getOrElse(ifNone); } /** - * Applies an action to this value, if this option is defined, otherwise does nothing. + * Executes the given action on the contained value if this {@code Option} is defined ({@code Some}), + * otherwise does nothing. * - * @param action An action which can be applied to an optional value + * @param action a consumer to apply to the contained value * @return this {@code Option} + * @throws NullPointerException if {@code action} is null */ @Override default Option peek(Consumer action) { @@ -440,11 +456,11 @@ default Option peek(Consumer action) { } /** - * Transforms this {@code Option}. + * Transforms this {@code Option} into a value of type {@code U} using the given function. * - * @param f A transformation - * @param Type of transformation result - * @return An instance of type {@code U} + * @param f a function to transform this {@code Option} + * @param the type of the result + * @return the result of applying {@code f} to this {@code Option} * @throws NullPointerException if {@code f} is null */ default U transform(Function, ? extends U> f) { diff --git a/vavr/src/main/java/io/vavr/control/Try.java b/vavr/src/main/java/io/vavr/control/Try.java index 34a89877f..f8092aee4 100644 --- a/vavr/src/main/java/io/vavr/control/Try.java +++ b/vavr/src/main/java/io/vavr/control/Try.java @@ -37,35 +37,39 @@ import static io.vavr.control.TryModule.sneakyThrow; /** - * The Try control gives us the ability write safe code without focusing on try-catch blocks in the presence of exceptions. + * A control structure that allows writing safe code without explicitly managing try-catch blocks for exceptions. *

- * The following exceptions are considered to be fatal/non-recoverable: + * The following exceptions are considered fatal or non-recoverable: *

    - *
  • {@linkplain InterruptedException}
  • - *
  • {@linkplain LinkageError}
  • - *
  • {@linkplain ThreadDeath}
  • - *
  • {@linkplain VirtualMachineError} (i.e. {@linkplain OutOfMemoryError} or {@linkplain StackOverflowError})
  • + *
  • {@linkplain InterruptedException}
  • + *
  • {@linkplain LinkageError}
  • + *
  • {@linkplain ThreadDeath}
  • + *
  • {@linkplain VirtualMachineError}, including {@linkplain OutOfMemoryError} and {@linkplain StackOverflowError}
  • *
*

- * Important note: Try may re-throw (undeclared) exceptions, e.g. on {@code get()}. From within a - * dynamic proxy {@link java.lang.reflect.InvocationHandler} this will lead to an - * {@link java.lang.reflect.UndeclaredThrowableException}. For more information, please read - * Dynamic Proxy Classes. + * Note: Methods such as {@code get()} may re-throw exceptions without declaring them. When used + * within a {@link java.lang.reflect.InvocationHandler} of a dynamic proxy, such exceptions will be wrapped in + * {@link java.lang.reflect.UndeclaredThrowableException}. See + * + * Dynamic Proxy Classes for more details. * - * @param Value type in the case of success. - * @author Daniel Dietrich + * @param the type of the value in case of success + * @author Daniel */ public interface Try extends Value, Serializable { long serialVersionUID = 1L; /** - * Creates a Try of a CheckedFunction0. + * Creates a {@link Try} instance from a {@link CheckedFunction0}. + *

+ * If the supplier executes without throwing an exception, a {@link Success} containing the result is returned. + * If an exception occurs during execution, a {@link Failure} wrapping the thrown exception is returned. * - * @param supplier A checked supplier - * @param Component type - * @return {@code Success(supplier.apply())} if no exception occurs, otherwise {@code Failure(throwable)} if an - * exception occurs calling {@code supplier.apply()}. + * @param supplier the checked supplier to execute + * @param the type of the value returned by the supplier + * @return a {@link Success} with the supplier's result, or a {@link Failure} if an exception is thrown + * @throws NullPointerException if {@code supplier} is {@code null} */ static Try of(CheckedFunction0 supplier) { Objects.requireNonNull(supplier, "supplier is null"); @@ -78,12 +82,15 @@ static Try of(CheckedFunction0 supplier) { /** - * Creates a Try of a Supplier. + * Creates a {@link Try} instance from a {@link Supplier}. + *

+ * If the supplier executes without throwing an exception, a {@link Success} containing the result is returned. + * If an exception occurs during execution, a {@link Failure} wrapping the thrown exception is returned. * - * @param supplier A supplier - * @param Component type - * @return {@code Success(supplier.get())} if no exception occurs, otherwise {@code Failure(throwable)} if an - * exception occurs calling {@code supplier.get()}. + * @param supplier the supplier to execute + * @param the type of the value returned by the supplier + * @return a {@link Success} with the supplier's result, or a {@link Failure} if an exception is thrown + * @throws NullPointerException if {@code supplier} is {@code null} */ static Try ofSupplier(Supplier supplier) { Objects.requireNonNull(supplier, "supplier is null"); @@ -91,12 +98,15 @@ static Try ofSupplier(Supplier supplier) { } /** - * Creates a Try of a Callable. + * Creates a {@link Try} instance from a {@link Callable}. + *

+ * If the callable executes without throwing an exception, a {@link Success} containing the result is returned. + * If an exception occurs during execution, a {@link Failure} wrapping the thrown exception is returned. * - * @param callable A callable - * @param Component type - * @return {@code Success(callable.call())} if no exception occurs, otherwise {@code Failure(throwable)} if an - * exception occurs calling {@code callable.call()}. + * @param callable the callable to execute + * @param the type of the value returned by the callable + * @return a {@link Success} with the callable's result, or a {@link Failure} if an exception is thrown + * @throws NullPointerException if {@code callable} is {@code null} */ static Try ofCallable(Callable callable) { Objects.requireNonNull(callable, "callable is null"); @@ -104,11 +114,15 @@ static Try ofCallable(Callable callable) { } /** - * Creates a Try of a CheckedRunnable. + * Creates a {@link Try} instance from a {@link CheckedRunnable}. + *

+ * If the runnable executes without throwing an exception, a {@link Success} containing {@code null} (representing + * the absence of a value) is returned. If an exception occurs during execution, a {@link Failure} wrapping the + * thrown exception is returned. * - * @param runnable A checked runnable - * @return {@code Success(null)} if no exception occurs, otherwise {@code Failure(throwable)} if an exception occurs - * calling {@code runnable.run()}. + * @param runnable the checked runnable to execute + * @return a {@link Success} with {@code null} if the runnable completes successfully, or a {@link Failure} if an exception is thrown + * @throws NullPointerException if {@code runnable} is {@code null} */ static Try run(CheckedRunnable runnable) { Objects.requireNonNull(runnable, "runnable is null"); @@ -121,26 +135,33 @@ static Try run(CheckedRunnable runnable) { } /** - * Creates a Try of a Runnable. + * Creates a {@link Try} instance from a {@link Runnable}. + *

+ * If the runnable executes without throwing an exception, a {@link Success} containing {@code null} (representing + * the absence of a value) is returned. If an exception occurs during execution, a {@link Failure} wrapping the + * thrown exception is returned. * - * @param runnable A runnable - * @return {@code Success(null)} if no exception occurs, otherwise {@code Failure(throwable)} if an exception occurs - * calling {@code runnable.run()}. + * @param runnable the runnable to execute + * @return a {@link Success} with {@code null} if the runnable completes successfully, or a {@link Failure} if an exception is thrown + * @throws NullPointerException if {@code runnable} is {@code null} */ static Try runRunnable(Runnable runnable) { Objects.requireNonNull(runnable, "runnable is null"); return run(runnable::run); } + /** - * Reduces many {@code Try}s into a single {@code Try} by transforming an - * {@code Iterable>} into a {@code Try>}. If any of - * the {@code Try}s are {@link Try.Failure}, then this returns a {@link Try.Failure}. + * Transforms an {@link Iterable} of {@link Try} instances into a single {@link Try} containing a {@link Seq} + * of all successful results. + *

+ * If any element in the input iterable is a {@link Try.Failure}, the resulting {@link Try} will also be a + * {@link Try.Failure}, containing the first encountered failure's cause. * - * @param values An {@link Iterable} of {@code Try}s - * @param type of the Trys - * @return A {@code Try} of a {@link Seq} of results - * @throws NullPointerException if {@code values} is null + * @param values an {@link Iterable} of {@code Try} instances + * @param the type of values contained in the {@code Try}s + * @return a {@link Try} containing a {@link Seq} of all successful results, or a {@link Try.Failure} if any input is a failure + * @throws NullPointerException if {@code values} is {@code null} */ static Try> sequence(Iterable> values) { Objects.requireNonNull(values, "values is null"); @@ -155,15 +176,18 @@ static Try> sequence(Iterable> values) { } /** - * Maps the values of an iterable to a sequence of mapped values into a single {@code Try} by - * transforming an {@code Iterable} into a {@code Try>}. + * Transforms an {@link Iterable} of values into a single {@link Try} containing a {@link Seq} of mapped results. + *

+ * Each value in the input iterable is mapped using the provided {@code mapper} function, which produces a + * {@link Try}. If all mappings succeed, a {@link Success} containing a {@link Seq} of results is returned. + * If any mapping results in a {@link Try.Failure}, the first encountered failure is returned. * - * @param values An {@code Iterable} of values. - * @param mapper A mapper of values to Trys - * @param The type of the given values. - * @param The mapped value type. - * @return A {@code Try} of a {@link Seq} of results. - * @throws NullPointerException if values or f is null. + * @param values an {@link Iterable} of input values + * @param mapper a function mapping each input value to a {@link Try} of the mapped result + * @param the type of the input values + * @param the type of the mapped results + * @return a {@link Try} containing a {@link Seq} of all mapped results, or a {@link Try.Failure} if any mapping fails + * @throws NullPointerException if {@code values} or {@code mapper} is {@code null} */ static Try> traverse(Iterable values, Function> mapper) { Objects.requireNonNull(values, "values is null"); @@ -172,35 +196,39 @@ static Try> traverse(Iterable values, Function(value)}. + * Creates a {@link Success} containing the given {@code value}. + *

+ * This is a convenience method equivalent to {@code new Success<>(value)}. * - * @param value A value. - * @param Type of the given {@code value}. - * @return A new {@code Success}. + * @param value the value to wrap in a {@link Success} + * @param the type of the value + * @return a new {@link Success} containing {@code value} */ static Try success(T value) { return new Success<>(value); } /** - * Creates a {@link Failure} that contains the given {@code exception}. Shortcut for {@code new Failure<>(exception)}. + * Creates a {@link Failure} containing the given {@code exception}. + *

+ * This is a convenience method equivalent to {@code new Failure<>(exception)}. * - * @param exception An exception. - * @param Component type of the {@code Try}. - * @return A new {@code Failure}. + * @param exception the exception to wrap in a {@link Failure} + * @param the component type of the {@code Try} + * @return a new {@link Failure} containing {@code exception} */ static Try failure(Throwable exception) { return new Failure<>(exception); } /** - * Narrows a widened {@code Try} to {@code Try} - * by performing a type-safe cast. This is eligible because immutable/read-only - * collections are covariant. + * Narrows a {@code Try} to {@code Try} using a type-safe cast. + *

+ * This is safe because {@code Try} is immutable and its contents are read-only, allowing covariance. * - * @param t A {@code Try}. - * @param Component type of the {@code Try}. - * @return the given {@code t} instance as narrowed type {@code Try}. + * @param t the {@code Try} instance to narrow + * @param the component type of the {@code Try} + * @return the given {@code Try} instance as {@code Try} */ @SuppressWarnings("unchecked") static Try narrow(Try t) { @@ -208,35 +236,37 @@ static Try narrow(Try t) { } /** - * Shortcut for {@code andThenTry(consumer::accept)}, see {@link #andThenTry(CheckedConsumer)}. + * Performs the given {@link Consumer} on the value of this {@code Try} if it is a {@link Success}. + *

+ * This is a shortcut for {@code andThenTry(consumer::accept)}. If this {@code Try} is a {@link Failure}, + * it is returned unchanged. If the consumer throws an exception, a {@link Failure} is returned. * - * @param consumer A consumer - * @return this {@code Try} if this is a {@code Failure} or the consumer succeeded, otherwise the - * {@code Failure} of the consumption. - * @throws NullPointerException if {@code consumer} is null + * @param consumer the consumer to execute on the value + * @return this {@code Try} if it is a {@link Failure} or the consumer succeeds, otherwise a {@link Failure} of the consumer + * @throws NullPointerException if {@code consumer} is {@code null} + * @see #andThenTry(CheckedConsumer) */ default Try andThen(Consumer consumer) { Objects.requireNonNull(consumer, "consumer is null"); return andThenTry(consumer::accept); } + /** - * Passes the result to the given {@code consumer} if this is a {@code Success}. + * Passes the result of this {@code Try} to the given {@link CheckedConsumer} if this is a {@link Success}. *

- * The main use case is chaining checked functions using method references: - * - *

-     * 
-     * Try.of(() -> 100)
-     *    .andThen(i -> System.out.println(i));
-     *
-     * 
-     * 
+ * This allows chaining of operations that may throw checked exceptions. If this {@code Try} is a {@link Failure}, + * it is returned unchanged. If the consumer throws an exception, a {@link Failure} containing that exception is returned. + *

+ * Example usage: + *


+     * Try.of(() -> 100)
+     *    .andThenTry(i -> System.out.println(i));
+     * 
* - * @param consumer A checked consumer - * @return this {@code Try} if this is a {@code Failure} or the consumer succeeded, otherwise the - * {@code Failure} of the consumption. - * @throws NullPointerException if {@code consumer} is null + * @param consumer the checked consumer to execute on the value + * @return this {@code Try} if it is a {@link Failure} or the consumer succeeds, otherwise a {@link Failure} of the consumer + * @throws NullPointerException if {@code consumer} is {@code null} */ default Try andThenTry(CheckedConsumer consumer) { Objects.requireNonNull(consumer, "consumer is null"); @@ -253,49 +283,52 @@ default Try andThenTry(CheckedConsumer consumer) { } /** - * Shortcut for {@code andThenTry(runnable::run)}, see {@link #andThenTry(CheckedRunnable)}. + * Performs the given {@link Runnable} if this {@code Try} is a {@link Success}. + *

+ * This is a shortcut for {@code andThenTry(runnable::run)}. If this {@code Try} is a {@link Failure}, it is returned unchanged. + * If the runnable throws an exception, a {@link Failure} containing that exception is returned. * - * @param runnable A runnable - * @return this {@code Try} if this is a {@code Failure} or the runnable succeeded, otherwise the - * {@code Failure} of the run. - * @throws NullPointerException if {@code runnable} is null + * @param runnable the runnable to execute + * @return this {@code Try} if it is a {@link Failure} or the runnable succeeds, otherwise a {@link Failure} of the runnable + * @throws NullPointerException if {@code runnable} is {@code null} + * @see #andThenTry(CheckedRunnable) */ default Try andThen(Runnable runnable) { Objects.requireNonNull(runnable, "runnable is null"); return andThenTry(runnable::run); } + /** - * Runs the given runnable if this is a {@code Success}, otherwise returns this {@code Failure}. + * Executes the given {@link CheckedRunnable} if this {@code Try} is a {@link Success}; + * otherwise, returns this {@code Failure}. *

- * The main use case is chaining runnables using method references: - * - *

-     * 
-     * Try.run(A::methodRef).andThen(B::methodRef).andThen(C::methodRef);
-     * 
-     * 
- * - * Please note that these lines are semantically the same: - * - *
-     * 
+     * This allows chaining of runnables that may throw checked exceptions. If the runnable throws an exception,
+     * a {@link Failure} containing that exception is returned.
+     * 

+ * Example usage with method references: + *


+     * Try.run(A::methodRef)
+     *    .andThen(B::methodRef)
+     *    .andThen(C::methodRef);
+     * 
+ * + * The following two forms are semantically equivalent: + *

      * Try.run(this::doStuff)
      *    .andThen(this::doMoreStuff)
      *    .andThen(this::doEvenMoreStuff);
      *
-     * Try.run(() -> {
+     * Try.run(() -> {
      *     doStuff();
      *     doMoreStuff();
      *     doEvenMoreStuff();
      * });
-     * 
-     * 
+ *
* - * @param runnable A checked runnable - * @return this {@code Try} if this is a {@code Failure} or the runnable succeeded, otherwise the - * {@code Failure} of the run. - * @throws NullPointerException if {@code runnable} is null + * @param runnable the checked runnable to execute + * @return this {@code Try} if it is a {@link Failure} or the runnable succeeds, otherwise a {@link Failure} of the runnable + * @throws NullPointerException if {@code runnable} is {@code null} */ default Try andThenTry(CheckedRunnable runnable) { Objects.requireNonNull(runnable, "runnable is null"); @@ -312,23 +345,23 @@ default Try andThenTry(CheckedRunnable runnable) { } /** - * Collects value that is in the domain of the given {@code partialFunction} by mapping the value to type {@code R}. - * - *
{@code
-     * partialFunction.isDefinedAt(value)
-     * }
- * - * If the element makes it through that filter, the mapped instance is wrapped in {@code Try} - * + * Transforms the value of this {@code Try} using the given {@link PartialFunction} if it is defined at the value. + *

+ * The {@code partialFunction} is first tested with {@link PartialFunction#isDefinedAt(Object)}. If it returns + * {@code true}, the value is mapped using {@link PartialFunction#apply(Object)} and wrapped in a new {@code Try}. + * If the function is not defined at the value or this {@code Try} is a {@link Failure}, the result is a {@link Failure}. + *

+ * Example: *

{@code
-     * R newValue = partialFunction.apply(value)
+     * PartialFunction pf = ...;
+     * Try.of(() -> 42)
+     *    .collect(pf); // maps the value if pf.isDefinedAt(42) is true
      * }
* - * - * @param partialFunction A function that is not necessarily defined on value of this try. - * @param The new value type - * @return A new {@code Try} instance containing value of type {@code R} - * @throws NullPointerException if {@code partialFunction} is null + * @param partialFunction a function that may not be defined for all input values + * @param the type of the mapped result + * @return a new {@code Try} containing the mapped value if defined, or a {@link Failure} + * @throws NullPointerException if {@code partialFunction} is {@code null} */ @SuppressWarnings("unchecked") default Try collect(PartialFunction partialFunction){ @@ -337,10 +370,11 @@ default Try collect(PartialFunction partialFuncti } /** - * Returns {@code Success(throwable)} if this is a {@code Failure(throwable)}, otherwise - * a {@code Failure(new NoSuchElementException("Success.failed()"))} if this is a Success. + * Returns a {@code Success} containing the throwable if this {@code Try} is a {@link Failure}. + *

+ * If this {@code Try} is a {@link Success}, a {@code Failure} containing a {@link NoSuchElementException} is returned. * - * @return a new Try + * @return a {@code Try} representing the throwable of this {@link Failure}, or a {@link Failure} if this is a {@link Success} */ default Try failed() { if (isFailure()) { @@ -351,13 +385,15 @@ default Try failed() { } /** - * Shortcut for {@code filterTry(predicate::test, throwableSupplier)}, see - * {@link #filterTry(CheckedPredicate, Supplier)}}. + * Returns a {@code Try} if the given {@link Predicate} evaluates to {@code true}, otherwise returns a {@link Failure} + * created by the given {@link Supplier} of {@link Throwable}. + *

+ * This is a shortcut for {@link #filterTry(CheckedPredicate, Supplier)}. * - * @param predicate A predicate - * @param throwableSupplier A supplier of a throwable - * @return a {@code Try} instance - * @throws NullPointerException if {@code predicate} or {@code throwableSupplier} is null + * @param predicate the predicate to test the value + * @param throwableSupplier a supplier providing a throwable if the predicate fails + * @return this {@code Try} if the predicate passes, otherwise a {@link Failure} from the throwable supplier + * @throws NullPointerException if {@code predicate} or {@code throwableSupplier} is {@code null} */ default Try filter(Predicate predicate, Supplier throwableSupplier) { Objects.requireNonNull(predicate, "predicate is null"); @@ -366,13 +402,15 @@ default Try filter(Predicate predicate, Supplier + * This is a shortcut for {@link #filterTry(CheckedPredicate, CheckedFunction1)}. * - * @param predicate A predicate - * @param errorProvider A function that provides some kind of Throwable for T - * @return a {@code Try} instance - * @throws NullPointerException if {@code predicate} or {@code errorProvider} is null + * @param predicate the predicate to test the value + * @param errorProvider a function providing a throwable if the predicate fails + * @return this {@code Try} if the predicate passes, otherwise a {@link Failure} from the error provider + * @throws NullPointerException if {@code predicate} or {@code errorProvider} is {@code null} */ default Try filter(Predicate predicate, Function errorProvider) { Objects.requireNonNull(predicate, "predicate is null"); @@ -381,11 +419,13 @@ default Try filter(Predicate predicate, Function + * This is a shortcut for {@link #filterTry(CheckedPredicate)}. * - * @param predicate A predicate - * @return a {@code Try} instance - * @throws NullPointerException if {@code predicate} is null + * @param predicate the predicate to test the value + * @return this {@code Try} if the predicate passes, otherwise a {@link Failure} + * @throws NullPointerException if {@code predicate} is {@code null} */ default Try filter(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); @@ -393,16 +433,17 @@ default Try filter(Predicate predicate) { } /** - * Returns {@code this} if this is a Failure or this is a Success and the value satisfies the predicate. + * Returns {@code this} if this {@code Try} is a {@link Failure} or if it is a {@link Success} and the value + * satisfies the given checked predicate. *

- * Returns a new Failure, if this is a Success and the value does not satisfy the Predicate or an exception - * occurs testing the predicate. The returned Failure wraps a Throwable instance provided by the given - * {@code throwableSupplier}. + * If this is a {@link Success} and the predicate returns {@code false}, or if evaluating the predicate + * throws an exception, a new {@link Failure} is returned. The returned failure wraps a {@link Throwable} + * provided by the given {@code throwableSupplier}. * - * @param predicate A checked predicate - * @param throwableSupplier A supplier of a throwable - * @return a {@code Try} instance - * @throws NullPointerException if {@code predicate} or {@code throwableSupplier} is null + * @param predicate the checked predicate to test the value + * @param throwableSupplier a supplier providing the {@link Throwable} for the failure if the predicate does not hold + * @return this {@code Try} if it is a {@link Failure} or the predicate passes, otherwise a {@link Failure} from the supplier + * @throws NullPointerException if {@code predicate} or {@code throwableSupplier} is {@code null} */ default Try filterTry(CheckedPredicate predicate, Supplier throwableSupplier) { Objects.requireNonNull(predicate, "predicate is null"); @@ -424,16 +465,16 @@ default Try filterTry(CheckedPredicate predicate, Supplier - * Returns a new Failure, if this is a Success and the value does not satisfy the Predicate or an exception - * occurs testing the predicate. The returned Failure wraps a Throwable instance provided by the given - * {@code errorProvider}. + * If the predicate does not hold or throws an exception, a new {@link Failure} is returned. The returned + * failure wraps a {@link Throwable} provided by the given {@code errorProvider} function. * - * @param predicate A checked predicate - * @param errorProvider A provider of a throwable - * @return a {@code Try} instance - * @throws NullPointerException if {@code predicate} or {@code errorProvider} is null + * @param predicate the checked predicate to test the value + * @param errorProvider a function that provides a {@link Throwable} if the predicate fails + * @return this {@code Try} if it is a {@link Failure} or the predicate passes, otherwise a {@link Failure} from the error provider + * @throws NullPointerException if {@code predicate} or {@code errorProvider} is {@code null} */ default Try filterTry(CheckedPredicate predicate, CheckedFunction1 errorProvider) { Objects.requireNonNull(predicate, "predicate is null"); @@ -442,14 +483,15 @@ default Try filterTry(CheckedPredicate predicate, CheckedFunction1 } /** - * Returns {@code this} if this is a Failure or this is a Success and the value satisfies the predicate. + * Returns {@code this} if this {@code Try} is a {@link Failure} or if it is a {@link Success} and the value + * satisfies the given checked predicate. *

- * Returns a new Failure, if this is a Success and the value does not satisfy the Predicate or an exception - * occurs testing the predicate. The returned Failure wraps a {@link NoSuchElementException} instance. + * If the predicate does not hold or throws an exception, a new {@link Failure} wrapping a + * {@link NoSuchElementException} is returned. * - * @param predicate A checked predicate - * @return a {@code Try} instance - * @throws NullPointerException if {@code predicate} is null + * @param predicate the checked predicate to test the value + * @return this {@code Try} if it is a {@link Failure} or the predicate passes, otherwise a {@link Failure} with a {@link NoSuchElementException} + * @throws NullPointerException if {@code predicate} is {@code null} */ default Try filterTry(CheckedPredicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); @@ -457,12 +499,15 @@ default Try filterTry(CheckedPredicate predicate) { } /** - * Shortcut for {@code flatMapTry(mapper::apply)}, see {@link #flatMapTry(CheckedFunction1)}. + * Transforms the value of this {@code Try} using the given {@link Function} if it is a {@link Success}, + * or returns this {@link Failure}. + *

+ * This is a shortcut for {@link #flatMapTry(CheckedFunction1)}. * - * @param mapper A mapper - * @param The new component type - * @return a {@code Try} - * @throws NullPointerException if {@code mapper} is null + * @param mapper a function mapping the value to another {@code Try} + * @param the type of the resulting {@code Try} + * @return a new {@code Try} resulting from applying the mapper, or this {@code Failure} if this is a failure + * @throws NullPointerException if {@code mapper} is {@code null} */ default Try flatMap(Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); @@ -470,12 +515,15 @@ default Try flatMap(Function> mappe } /** - * FlatMaps the value of a Success or returns a Failure. + * Transforms the value of this {@code Try} using the given {@link CheckedFunction1} if it is a {@link Success}, + * or returns this {@link Failure}. + *

+ * If applying the mapper throws an exception, a {@link Failure} containing the exception is returned. * - * @param mapper A mapper - * @param The new component type - * @return a {@code Try} - * @throws NullPointerException if {@code mapper} is null + * @param mapper a checked function mapping the value to another {@code Try} + * @param the type of the resulting {@code Try} + * @return a new {@code Try} resulting from applying the mapper, or this {@code Failure} if this is a failure + * @throws NullPointerException if {@code mapper} is {@code null} */ @SuppressWarnings("unchecked") default Try flatMapTry(CheckedFunction1> mapper) { @@ -492,29 +540,29 @@ default Try flatMapTry(CheckedFunction1 - * IMPORTANT! If this is a {@link Failure}, the underlying {@code cause} of type {@link Throwable} is thrown. + * Returns the value of this {@code Try} if it is a {@link Success}, or throws the underlying exception if it is a {@link Failure}. *

- * The thrown exception is exactly the same as the result of {@link #getCause()}. + * Important: If this {@code Try} is a {@link Failure}, the exception thrown is exactly the + * {@link #getCause()} of this {@code Failure}. * - * @return The result of this {@code Try}. + * @return the value contained in this {@code Success} + * throws Throwable the underlying cause sneakily if this is a {@link Failure} */ @Override T get(); /** - * Gets the cause if this is a Failure or throws if this is a Success. + * Returns the cause of failure if this {@code Try} is a {@link Failure}. * - * @return The cause if this is a Failure - * @throws UnsupportedOperationException if this is a Success + * @return the throwable cause of this {@link Failure} + * @throws UnsupportedOperationException if this {@code Try} is a {@link Success} */ Throwable getCause(); /** - * A {@code Try}'s value is computed synchronously. + * Indicates whether this {@code Try} is computed asynchronously. * - * @return false + * @return {@code false} for a regular {@code Try}, since the value is computed synchronously */ @Override default boolean isAsync() { @@ -522,24 +570,24 @@ default boolean isAsync() { } /** - * Checks whether this Try has no result, i.e. is a Failure. + * Checks whether this {@code Try} contains no value, i.e., it is a {@link Failure}. * - * @return true if this is a Failure, returns false if this is a Success. + * @return {@code true} if this is a {@link Failure}, {@code false} if this is a {@link Success} */ @Override boolean isEmpty(); /** - * Checks if this is a Failure. + * Checks whether this {@code Try} is a {@link Failure}. * - * @return true, if this is a Failure, otherwise false, if this is a Success + * @return {@code true} if this is a {@link Failure}, {@code false} if this is a {@link Success} */ boolean isFailure(); /** - * A {@code Try}'s value is computed eagerly. + * Indicates whether this {@code Try} is evaluated lazily. * - * @return false + * @return {@code false} for a standard {@code Try}, as its value is computed eagerly */ @Override default boolean isLazy() { @@ -547,9 +595,9 @@ default boolean isLazy() { } /** - * A {@code Try} is a single-valued. + * Indicates whether this {@code Try} represents a single value. * - * @return {@code true} + * @return {@code true}, since a {@code Try} always contains at most one value */ @Override default boolean isSingleValued() { @@ -557,9 +605,9 @@ default boolean isSingleValued() { } /** - * Checks if this is a Success. + * Checks whether this {@code Try} is a {@link Success}. * - * @return true, if this is a Success, otherwise false, if this is a Failure + * @return {@code true} if this is a {@link Success}, {@code false} if this is a {@link Failure} */ boolean isSuccess(); @@ -593,12 +641,14 @@ default Try mapToVoid() { } /** - * Maps the cause to a new exception if this is a {@code Failure} or returns this instance if this is a {@code Success}. + * Transforms the cause of this {@link Failure} using the given sequence of match cases. *

- * If none of the given cases matches the cause, the same {@code Failure} is returned. + * If this {@code Try} is a {@link Success}, it is returned unchanged. If this is a {@link Failure}, the + * cause is matched against the provided {@code cases}. If a match is found, a new {@link Failure} containing + * the mapped exception is returned. If none of the cases match, the original {@link Failure} is returned. * - * @param cases A not necessarily exhaustive sequence of cases that will be matched against a cause. - * @return A new {@code Try} if this is a {@code Failure}, otherwise this. + * @param cases a possibly non-exhaustive sequence of match cases to handle the cause + * @return a new {@code Try} with a mapped cause if a match is found, otherwise this {@code Try} */ @GwtIncompatible @SuppressWarnings({ "unchecked", "varargs" }) @@ -612,24 +662,21 @@ default Try mapFailure(Match.Case.. } /** - * Runs the given checked function if this is a {@link Try.Success}, - * passing the result of the current expression to it. - * If this expression is a {@link Try.Failure} then it'll return a new - * {@link Try.Failure} of type R with the original exception. + * Applies the given checked function to the value of this {@link Success}, or returns this {@link Failure} unchanged. *

- * The main use case is chaining checked functions using method references: - * - *

-     * 
-     * Try.of(() -> 0)
-     *    .map(x -> 1 / x); // division by zero
-     * 
-     * 
+ * If the function throws an exception, a new {@link Failure} containing the exception is returned. + * This allows chaining of computations that may throw checked exceptions. + *

+ * Example: + *


+     * Try.of(() -> 0)
+     *    .mapTry(x -> 1 / x); // division by zero will result in a Failure
+     * 
* - * @param The new component type - * @param mapper A checked function - * @return a {@code Try} - * @throws NullPointerException if {@code mapper} is null + * @param the type of the result + * @param mapper a checked function to apply to the value + * @return a new {@code Try} containing the mapped value if this is a {@link Success}, otherwise this {@link Failure} + * @throws NullPointerException if {@code mapper} is {@code null} */ @SuppressWarnings("unchecked") default Try mapTry(CheckedFunction1 mapper) { @@ -646,18 +693,19 @@ default Try mapTry(CheckedFunction1 mapper) { } /** - * Consumes the cause if this is a {@link Try.Failure}. - * + * Performs the given action if this {@link Try} is a {@link Failure}. + *

+ * Example: *

{@code
-     * // (does not print anything)
+     * // does not print anything
      * Try.success(1).onFailure(System.out::println);
      *
      * // prints "java.lang.Error"
      * Try.failure(new Error()).onFailure(System.out::println);
      * }
* - * @param action An exception consumer - * @return this + * @param action a consumer of the throwable cause + * @return this {@code Try} instance * @throws NullPointerException if {@code action} is null */ default Try onFailure(Consumer action) { @@ -669,10 +717,11 @@ default Try onFailure(Consumer action) { } /** - * Consumes the cause if this is a {@link Try.Failure} and the cause is instance of {@code X}. - * + * Performs the given action if this {@link Try} is a {@link Failure} and the cause is an instance of the specified type. + *

+ * Example: *

{@code
-     * // (does not print anything)
+     * // does not print anything
      * Try.success(1).onFailure(Error.class, System.out::println);
      *
      * // prints "Error"
@@ -680,11 +729,11 @@ default Try onFailure(Consumer action) {
      *    .onFailure(RuntimeException.class, x -> System.out.println("Runtime exception"))
      *    .onFailure(Error.class, x -> System.out.println("Error"));
      * }
- * - * @param exceptionType the exception type that is handled - * @param action an excpetion consumer - * @param the exception type that should be handled - * @return this + * + * @param exceptionType the type of exception to handle + * @param action a consumer for the exception + * @param the type of exception that should be handled + * @return this {@code Try} instance * @throws NullPointerException if {@code exceptionType} or {@code action} is null */ @GwtIncompatible @@ -699,18 +748,19 @@ default Try onFailure(Class exceptionType, Consumer< } /** - * Consumes the value if this is a {@link Try.Success}. - * + * Performs the given action if this {@link Try} is a {@link Success}. + *

+ * Example: *

{@code
      * // prints "1"
      * Try.success(1).onSuccess(System.out::println);
      *
-     * // (does not print anything)
+     * // does not print anything
      * Try.failure(new Error()).onSuccess(System.out::println);
      * }
* - * @param action A value consumer - * @return this + * @param action a consumer of the value + * @return this {@code Try} instance * @throws NullPointerException if {@code action} is null */ default Try onSuccess(Consumer action) { @@ -721,18 +771,41 @@ default Try onSuccess(Consumer action) { return this; } + /** + * Returns this {@code Try} if it is a {@link Success}, or the given alternative {@code Try} if this is a {@link Failure}. + * + * @param other the alternative {@code Try} to return if this is a {@link Failure} + * @return this {@code Try} if success, otherwise {@code other} + * @throws NullPointerException if {@code other} is null + */ @SuppressWarnings("unchecked") default Try orElse(Try other) { Objects.requireNonNull(other, "other is null"); return isSuccess() ? this : (Try) other; } + /** + * Returns this {@code Try} if it is a {@link Success}, or a {@code Try} supplied by the given {@link Supplier} if this is a {@link Failure}. + *

+ * The supplier is only invoked if this {@code Try} is a {@link Failure}. + * + * @param supplier a supplier of an alternative {@code Try} + * @return this {@code Try} if success, otherwise the {@code Try} returned by {@code supplier} + * @throws NullPointerException if {@code supplier} is null + */ @SuppressWarnings("unchecked") default Try orElse(Supplier> supplier) { Objects.requireNonNull(supplier, "supplier is null"); return isSuccess() ? this : (Try) supplier.get(); } + /** + * Returns the value of this {@code Success}, or applies the given function to the cause if this is a {@link Failure}. + * + * @param other a function mapping the throwable cause to a replacement value + * @return the value of this {@link Success}, or the result of applying {@code other} to the failure cause + * @throws NullPointerException if {@code other} is null + */ default T getOrElseGet(Function other) { Objects.requireNonNull(other, "other is null"); if (isFailure()) { @@ -742,6 +815,14 @@ default T getOrElseGet(Function other) { } } + /** + * Executes the given action if this {@code Try} is a {@link Failure}. + *

+ * This method is typically used for side-effecting handling of failure cases. + * + * @param action a consumer of the throwable cause + * @throws NullPointerException if {@code action} is null + */ default void orElseRun(Consumer action) { Objects.requireNonNull(action, "action is null"); if (isFailure()) { @@ -749,6 +830,18 @@ default void orElseRun(Consumer action) { } } + + /** + * Returns the value of this {@link Success}, or throws a provided exception if this is a {@link Failure}. + *

+ * The exception to throw is created by applying the given {@code exceptionProvider} function to the cause of the failure. + * + * @param the type of the exception to throw + * @param exceptionProvider a function mapping the throwable cause to an exception to be thrown + * @return the value of this {@link Success} + * @throws X the exception provided by {@code exceptionProvider} if this is a {@link Failure} + * @throws NullPointerException if {@code exceptionProvider} is null + */ default T getOrElseThrow(Function exceptionProvider) throws X { Objects.requireNonNull(exceptionProvider, "exceptionProvider is null"); if (isFailure()) { @@ -759,12 +852,16 @@ default T getOrElseThrow(Function ex } /** - * Folds either the {@code Failure} or the {@code Success} side of the Try value. + * Folds this {@code Try} into a single value by applying one of two functions: + * one for the failure case and one for the success case. + *

+ * If this is a {@link Failure}, the {@code ifFail} function is applied to the cause. + * If this is a {@link Success}, the {@code f} function is applied to the value. * - * @param ifFail maps the left value if this is a {@code Failure} - * @param f maps the value if this is a {@code Success} - * @param type of the folded value - * @return A value of type X + * @param ifFail maps the throwable cause if this is a {@link Failure} + * @param f maps the value if this is a {@link Success} + * @param the type of the result + * @return the result of applying the corresponding function */ default X fold(Function ifFail, Function f) { if (isFailure()) { @@ -775,10 +872,12 @@ default X fold(Function ifFail, Function + * This method is useful for side-effecting operations without transforming the value. * - * @param action A Consumer - * @return this {@code Try} + * @param action a consumer of the value + * @return this {@code Try} instance * @throws NullPointerException if {@code action} is null */ @Override @@ -790,11 +889,15 @@ default Try peek(Consumer action) { return this; } + /** - * Returns {@code this}, if this is a {@code Success} or this is a {@code Failure} and the cause is not assignable - * from {@code cause.getClass()}. Otherwise tries to recover the exception of the failure with {@code f}, - * i.e. calling {@code Try.of(() -> f.apply((X) getCause())}. - * + * Attempts to recover from a failure if the cause is an instance of the specified exception type. + *

+ * If this {@code Try} is a {@link Success}, it is returned unchanged. If this is a {@link Failure} and the cause + * is assignable from {@code exceptionType}, the recovery function {@code f} is applied to the cause inside a new {@code Try}. + * Otherwise, the original {@code Failure} is returned. + *

+ * Example: *

{@code
      * // = Success(13)
      * Try.of(() -> 27/2).recover(ArithmeticException.class, x -> Integer.MAX_VALUE);
@@ -808,11 +911,11 @@ default Try peek(Consumer action) {
      * Try.of(() -> 1/0).recover(Error.class, x -> Integer.MAX_VALUE);
      * }
* - * @param Exception type - * @param exceptionType The specific exception type that should be handled - * @param f A recovery function taking an exception of type {@code X} - * @return a {@code Try} - * @throws NullPointerException if {@code exception} is null or {@code f} is null + * @param the type of exception to handle + * @param exceptionType the specific exception type that should be recovered + * @param f a recovery function taking an exception of type {@code X} and producing a value + * @return a {@code Success} with the recovered value if the exception matches, otherwise this {@code Try} + * @throws NullPointerException if {@code exceptionType} or {@code f} is null */ @GwtIncompatible @SuppressWarnings("unchecked") @@ -828,12 +931,16 @@ default Try recover(Class exceptionType, Function + * If this {@code Try} is a {@link Success}, it is returned unchanged. If this is a {@link Failure} and the cause + * is assignable from {@code exceptionType}, the recovery function {@code f} is applied to the cause and returns a new {@code Try}. + * If the returned {@code Try} is a {@link Try#isFailure()}, the recovery is considered unsuccessful. + * Otherwise, the original {@code Failure} is returned. + *

+ * Example: *

{@code
      * // = Success(13)
      * Try.of(() -> 27/2).recoverWith(ArithmeticException.class, x -> Try.success(Integer.MAX_VALUE));
@@ -846,20 +953,19 @@ default  Try recover(Class exceptionType, Function 1/0).recoverWith(Error.class, x -> Try.success(Integer.MAX_VALUE));
      * }
- * - * @param Exception type - * @param exceptionType The specific exception type that should be handled - * @param f A recovery function that takes an exception of type {@code X} and returns a new Try instance. - * The recovery is considered successful if the returned Try is a {@link Try#isSuccess()}. - * @return a {@code Try} + * + * @param the type of exception to handle + * @param exceptionType the specific exception type that should trigger recovery + * @param f a recovery function that takes an exception of type {@code X} and returns a new {@code Try} instance + * @return a {@code Try} representing the recovered value if the exception matches, otherwise this {@code Try} * @throws NullPointerException if {@code exceptionType} or {@code f} is null */ @GwtIncompatible @SuppressWarnings("unchecked") - default Try recoverWith(Class exceptionType, Function> f){ + default Try recoverWith(Class exceptionType, Function> f) { Objects.requireNonNull(exceptionType, "exceptionType is null"); Objects.requireNonNull(f, "f is null"); - if(isFailure()){ + if (isFailure()) { final Throwable cause = getCause(); if (exceptionType.isAssignableFrom(cause.getClass())) { try { @@ -872,10 +978,15 @@ default Try recoverWith(Class exceptionType, Functio return this; } + /** - * Recovers this {@code Try} with the given {@code recovered}, if this is a {@link Try.Failure} - * and the given {@code exceptionType} is assignable to the underlying cause type. - * + * Recovers this {@code Try} with the given {@code recovered} value if this is a {@link Try.Failure} + * and the underlying cause is assignable to the specified {@code exceptionType}. + *

+ * If this {@code Try} is a {@link Success}, or if the cause does not match {@code exceptionType}, + * the original {@code Try} is returned unchanged. + *

+ * Example: *

{@code
      * // = Success(13)
      * Try.of(() -> 27/2).recoverWith(ArithmeticException.class, Try.success(Integer.MAX_VALUE));
@@ -889,56 +1000,65 @@ default  Try recoverWith(Class exceptionType, Functio
      * Try.of(() -> 1/0).recoverWith(Error.class, Try.success(Integer.MAX_VALUE));
      * }
* - * @param exceptionType the exception type that is recovered - * @param recovered the substitute for a matching {@code Failure} - * @param type of the exception that should be recovered - * @return the given {@code recovered} if this is a {@link Try.Failure} and the cause is of type {@code X}, else {@code this} + * @param the type of exception to handle + * @param exceptionType the exception type that triggers recovery + * @param recovered a {@code Try} instance to return if the cause matches {@code exceptionType} + * @return the given {@code recovered} if the exception matches, otherwise this {@code Try} * @throws NullPointerException if {@code exceptionType} or {@code recovered} is null */ @GwtIncompatible - default Try recoverWith(Class exceptionType, Try recovered){ + default Try recoverWith(Class exceptionType, Try recovered) { Objects.requireNonNull(exceptionType, "exceptionType is null"); Objects.requireNonNull(recovered, "recovered is null"); return (isFailure() && exceptionType.isAssignableFrom(getCause().getClass())) - ? narrow(recovered) - : this; + ? narrow(recovered) + : this; } + /** - * Returns {@code this}, if this is a {@link Try.Success} or this is a {@code Failure} and the cause is not assignable - * from {@code cause.getClass()}. Otherwise returns a {@link Try.Success} containing the given {@code value}. - * + * Recovers this {@code Try} with the given {@code value} if this is a {@link Try.Failure} + * and the underlying cause matches the specified {@code exceptionType}. + *

+ * If this {@code Try} is a {@link Success}, or if the cause is not assignable from {@code exceptionType}, + * the original {@code Try} is returned unchanged. + *

+ * Example: *

{@code
      * // = Success(13)
-     * Try.of(() -> 27/2).recover(ArithmeticException.class, Integer.MAX_VALUE);
+     * Try.of(() -> 27/2).recover(ArithmeticException.class, 13);
      *
      * // = Success(2147483647)
      * Try.of(() -> 1/0)
-     *    .recover(Error.class, -1);
+     *    .recover(Error.class, -1)
      *    .recover(ArithmeticException.class, Integer.MAX_VALUE);
      *
      * // = Failure(java.lang.ArithmeticException: / by zero)
      * Try.of(() -> 1/0).recover(Error.class, Integer.MAX_VALUE);
      * }
* - * @param Exception type - * @param exceptionType The specific exception type that should be handled - * @param value A value that is used in case of a recovery - * @return a {@code Try} + * @param the type of exception to handle + * @param exceptionType the exception type that triggers recovery + * @param value the value to return in a {@link Try.Success} if the cause matches + * @return a {@code Try} containing the recovery value if the exception matches, otherwise this {@code Try} * @throws NullPointerException if {@code exceptionType} is null */ @GwtIncompatible default Try recover(Class exceptionType, T value) { Objects.requireNonNull(exceptionType, "exceptionType is null"); return (isFailure() && exceptionType.isAssignableFrom(getCause().getClass())) - ? Try.success(value) - : this; + ? Try.success(value) + : this; } + /** - * Returns {@code this}, if this is a {@code Success}, otherwise tries to recover the exception of the failure with {@code f}, - * i.e. calling {@code Try.of(() -> f.apply(throwable))}. - * + * Recovers this {@code Try} if it is a {@link Try.Failure} by applying the given recovery function {@code f} + * to the underlying exception. The result of the function is wrapped in a {@link Try.Success}. + *

+ * If this {@code Try} is already a {@link Success}, it is returned unchanged. + *

+ * Example: *

{@code
      * // = Success(13)
      * Try.of(() -> 27/2).recover(x -> Integer.MAX_VALUE);
@@ -947,8 +1067,8 @@ default  Try recover(Class exceptionType, T value) {
      * Try.of(() -> 1/0).recover(x -> Integer.MAX_VALUE);
      * }
* - * @param f A recovery function taking a Throwable - * @return a {@code Try} + * @param f A recovery function that takes the underlying exception and returns a value + * @return a {@code Try} containing either the original success value or the recovered value * @throws NullPointerException if {@code f} is null */ default Try recover(Function f) { @@ -960,11 +1080,16 @@ default Try recover(Function f) { } } + /** - * Returns {@code this}, if this is a Success, otherwise tries to recover the exception of the failure with {@code f}, - * i.e. calling {@code f.apply(cause.getCause())}. If an error occurs recovering a Failure, then the new Failure is - * returned. - * + * Recovers this {@code Try} if it is a {@link Try.Failure} by applying the given recovery function {@code f} + * to the underlying exception. The recovery function returns a new {@code Try} instance. + *

+ * If this {@code Try} is already a {@link Success}, it is returned unchanged. + * If an exception occurs while executing the recovery function, a new {@link Try.Failure} is returned + * wrapping that exception. + *

+ * Example: *

{@code
      * // = Success(13)
      * Try.of(() -> 27/2).recoverWith(x -> Try.success(Integer.MAX_VALUE));
@@ -973,8 +1098,8 @@ default Try recover(Function f) {
      * Try.of(() -> 1/0).recoverWith(x -> Try.success(Integer.MAX_VALUE));
      * }
* - * @param f A recovery function taking a Throwable - * @return a {@code Try} + * @param f A recovery function that takes the underlying exception and returns a new {@code Try} + * @return a {@code Try} containing either the original success value or the recovered {@code Try} * @throws NullPointerException if {@code f} is null */ @SuppressWarnings("unchecked") @@ -992,9 +1117,12 @@ default Try recoverWith(Function + * If this {@code Try} is already a {@link Success}, it is returned unchanged. The {@code recoveryAttempt} is + * evaluated using {@link Try#of(CheckedFunction0)}, and its result is wrapped in a new {@code Try}. + *

+ * Example: *

{@code
      * // = Success(5)
      * Try.of(() -> 5)
@@ -1005,8 +1133,8 @@ default Try recoverWith(Function 10);
      * }
* - * @param recoveryAttempt A checked function that provides a fallback in case of a failure - * @return a {@code Try} that is either this {@code Success} or a new {@code Try} evaluated from {@code recoveryAttempt} + * @param recoveryAttempt A checked supplier providing a fallback value in case of failure + * @return a {@code Try} containing either the original success value or the result of {@code recoveryAttempt} * @throws NullPointerException if {@code recoveryAttempt} is null */ default Try recoverAllAndTry(CheckedFunction0 recoveryAttempt) { @@ -1014,11 +1142,13 @@ default Try recoverAllAndTry(CheckedFunction0 recoveryAttempt) { return isFailure() ? of(recoveryAttempt) : this; } + /** - * Returns {@code this}, if this is a {@link Try.Success}, otherwise attempts to recover from failure when the - * underlying cause is assignable to the specified {@code exceptionType}, by evaluating the given + * Returns {@code this} if it is a {@link Try.Success}, or attempts to recover from a failure when the + * underlying cause is assignable to the specified {@code exceptionType} by evaluating the given * {@code recoveryAttempt} (via {@link Try#of(CheckedFunction0)}). - * + *

+ * Example usage: *

{@code
      * // = Success(5)
      * Try.of(() -> 5)
@@ -1033,24 +1163,28 @@ default Try recoverAllAndTry(CheckedFunction0 recoveryAttempt) {
      *    .recoverAndTry(NullPointerException.class, () -> 10);
      * }
* - * @param The type of the exception that may be recovered - * @param exceptionType The specific exception type that should trigger the recovery - * @param recoveryAttempt A checked function that provides a fallback in case of a matching failure - * @return a {@code Try} that is either this {@code Success}, or a new {@code Try} evaluated from {@code recoveryAttempt} + * @param The type of the exception that may be recovered + * @param exceptionType The specific exception type that triggers the recovery + * @param recoveryAttempt A checked function providing a fallback value if the exception matches + * @return a {@code Try} containing either the original success value or the result of {@code recoveryAttempt} * @throws NullPointerException if {@code exceptionType} or {@code recoveryAttempt} is null */ default Try recoverAndTry(Class exceptionType, CheckedFunction0 recoveryAttempt) { Objects.requireNonNull(exceptionType, "exceptionType is null"); Objects.requireNonNull(recoveryAttempt, "recoveryAttempt is null"); return isFailure() && exceptionType.isAssignableFrom(getCause().getClass()) - ? of(recoveryAttempt) - : this; + ? of(recoveryAttempt) + : this; } + /** * Converts this {@code Try} to an {@link Either}. + *

+ * If this is a {@link Try.Success}, the value is wrapped as a {@link Either#right(Object)}. + * If this is a {@link Try.Failure}, the cause is wrapped as a {@link Either#left(Object)}. * - * @return A new {@code Either} + * @return a new {@code Either} representing this {@code Try} */ default Either toEither() { if (isFailure()) { @@ -1061,13 +1195,13 @@ default Either toEither() { } /** - * Converts this {@code Try} to an {@link Either}, converting the Throwable (in the failure case) - * to a left value using the passed {@link Function}. + * Converts this {@code Try} to an {@link Either}, mapping the failure cause to a left value using + * the provided {@link Function}. * - * @param left type of the resulting Either - * @param throwableMapper A transformation from throwable to the left type of the new {@code Either} - * @return A new {@code Either} - * @throws NullPointerException if the given {@code throwableMapper} is null + * @param the left type of the resulting {@code Either} + * @param throwableMapper a function to convert the failure {@link Throwable} to type {@code L} + * @return a new {@code Either} representing this {@code Try} + * @throws NullPointerException if {@code throwableMapper} is null */ default Either toEither(Function throwableMapper) { Objects.requireNonNull(throwableMapper, "throwableMapper is null"); @@ -1080,25 +1214,29 @@ default Either toEither(Function throw /** * Converts this {@code Try} to a {@link Validation}. + *

+ * A {@link Try.Success} is converted to a {@link Validation#valid(Object)}, while + * a {@link Try.Failure} is converted to a {@link Validation#invalid(Object)} containing + * the cause. * - * @return A new {@code Validation} + * @return a new {@code Validation} representing this {@code Try} */ default Validation toValidation() { return toValidation(Function.identity()); } /** - * Converts this {@code Try} to a {@link Validation}, converting the Throwable (in the failure case) - * to another object using the passed {@link Function}. + * Converts this {@code Try} to a {@link Validation}, mapping the failure cause to an invalid value + * using the provided {@link Function}. * *

{@code
-     * Validation = Try.of(() -> 1/0).toValidation(Throwable::getMessage));
+     * Validation validation = Try.of(() -> 1/0).toValidation(Throwable::getMessage);
      * }
* - * @param result type of the throwable mapper - * @param throwableMapper A transformation from throwable to desired invalid type of new {@code Validation} - * @return A new {@code Validation} - * @throws NullPointerException if the given {@code throwableMapper} is null. + * @param the type of the invalid value + * @param throwableMapper a function to convert the failure {@link Throwable} to type {@code U} + * @return a {@code Validation} representing this {@code Try} + * @throws NullPointerException if {@code throwableMapper} is null */ default Validation toValidation(Function throwableMapper) { Objects.requireNonNull(throwableMapper, "throwableMapper is null"); @@ -1110,11 +1248,11 @@ default Validation toValidation(Function Type of transformation result - * @return An instance of type {@code U} + * @param f a transformation function + * @param the result type of the transformation + * @return the result of applying {@code f} to this {@code Try} * @throws NullPointerException if {@code f} is null */ default U transform(Function, ? extends U> f) { @@ -1123,10 +1261,11 @@ default U transform(Function, ? extends U> f) { } /** - * Provides try's finally behavior no matter what the result of the operation is. + * Executes a given {@link Runnable} after this {@code Try}, regardless of whether it is a + * {@link Try.Success} or {@link Try.Failure}. * - * @param runnable A runnable - * @return this {@code Try}. + * @param runnable a final action to perform + * @return this {@code Try} unchanged if the runnable succeeds, or a new {@link Try.Failure} if it throws * @throws NullPointerException if {@code runnable} is null */ default Try andFinally(Runnable runnable) { @@ -1135,10 +1274,11 @@ default Try andFinally(Runnable runnable) { } /** - * Provides try's finally behavior no matter what the result of the operation is. + * Executes a given {@link CheckedRunnable} after this {@code Try}, regardless of whether it is a + * {@link Try.Success} or {@link Try.Failure}. * - * @param runnable A runnable - * @return this {@code Try}. + * @param runnable a checked final action to perform + * @return this {@code Try} unchanged if the runnable succeeds, or a new {@link Try.Failure} if it throws * @throws NullPointerException if {@code runnable} is null */ default Try andFinallyTry(CheckedRunnable runnable) { @@ -1161,9 +1301,18 @@ default Try andFinallyTry(CheckedRunnable runnable) { String toString(); /** - * A succeeded Try. + * Represents a successful {@link Try} containing a value. + *

+ * Instances of this class indicate that the computation completed successfully + * and hold the resulting value of type {@code T}. + * + *

{@code
+     * Try success = new Try.Success<>(42);
+     * success.isSuccess(); // true
+     * success.get();       // 42
+     * }
* - * @param component type of this Success + * @param the type of the contained value * @author Daniel Dietrich */ final class Success implements Try, Serializable { @@ -1229,9 +1378,18 @@ public String toString() { } /** - * A failed Try. + * Represents a failed {@link Try} containing a {@link Throwable} as the cause. + *

+ * Instances of this class indicate that the computation threw an exception + * and do not contain a successful value. + * + *

{@code
+     * Try failure = new Try.Failure<>(new RuntimeException("error"));
+     * failure.isFailure();  // true
+     * failure.getCause();   // RuntimeException: error
+     * }
* - * @param component type of this Failure + * @param the type of the value that would have been contained if successful * @author Daniel Dietrich */ final class Failure implements Try, Serializable { @@ -1245,7 +1403,7 @@ final class Failure implements Try, Serializable { * * @param cause A cause of type Throwable, may not be null. * @throws NullPointerException if {@code cause} is null - * @throws Throwable if the given {@code cause} is fatal, i.e. non-recoverable + * throws Throwable sneakily, if the given {@code cause} is fatal, i.e. non-recoverable */ private Failure(Throwable cause) { Objects.requireNonNull(cause, "cause is null"); @@ -1788,7 +1946,7 @@ static R sneakyThrow(Throwable t) throws T { throw (T) t; } - static class ThreadDeathResolver { + class ThreadDeathResolver { static final Class THREAD_DEATH_CLASS = resolve(); static boolean isThreadDeath(Throwable throwable) { diff --git a/vavr/src/main/java/io/vavr/control/Validation.java b/vavr/src/main/java/io/vavr/control/Validation.java index d3bb8ec24..788d2b7f2 100644 --- a/vavr/src/main/java/io/vavr/control/Validation.java +++ b/vavr/src/main/java/io/vavr/control/Validation.java @@ -31,46 +31,49 @@ import java.util.function.Supplier; /** - * An implementation similar to scalaz's Validation control. + * An implementation similar to Scalaz's + * Validation control. * *

- * The Validation type is different from a Monad type, it is an applicative - * functor. Whereas a Monad will short circuit after the first error, the - * applicative functor will continue on, accumulating ALL errors. This is - * especially helpful in cases such as validation, where you want to know - * all the validation errors that have occurred, not just the first one. + * The {@code Validation} type is an applicative functor, not a Monad. While a Monad + * short-circuits on the first error, an applicative functor accumulates all errors, + * making it particularly useful for validation scenarios where all errors should be reported. *

* *
  * 
- * Validation construction:
+ * // Validation construction:
  *
- * Valid:
- * Validation<String,Integer> valid = Validation.valid(5);
+ * // Valid
+ * Validation<String, Integer> valid = Validation.valid(5);
  *
- * Invalid:
- * Validation<List<String>,Integer> invalid = Validation.invalid(List.of("error1","error2"));
+ * // Invalid
+ * Validation<List<String>, Integer>invalid = Validation.invalid(List.of("error1", "error2"));
  *
- * Validation combination:
+ * // Validation combination:
  *
- * Validation<String,String> valid1 = Validation.valid("John");
- * Validation<String,Integer> valid2 = Validation.valid(5);
- * Validation<String,Option<String>> valid3 = Validation.valid(Option.of("123 Fake St."));
- * Function3<String,Integer,Option<String>,Person> f = ...;
+ * Validation<String, String> valid1 = Validation.valid("John");
+ * Validation<String, Integer> valid2 = Validation.valid(5);
+ * Validation<String, Option<String>> valid3 = Validation.valid(Option.of("123 Fake St."));
+ * Function3<String, Integer, Option<String>, Person> f = ...;
  *
- * Validation<List<String>,String> result = valid1.combine(valid2).ap((name,age) -> "Name: "+name+" Age: "+age);
- * Validation<List<String>,Person> result2 = valid1.combine(valid2).combine(valid3).ap(f);
+ * Validation<List<String>, String> result =
+ *     valid1.combine(valid2).ap((name, age) -> "Name: " + name + " Age: " + age);
  *
- * Another form of combining validations:
+ * Validation<List<String>, Person> result2 =
+ *     valid1.combine(valid2).combine(valid3).ap(f);
  *
- * Validation<List<String>,Person> result3 = Validation.combine(valid1, valid2, valid3).ap(f);
+ * // Another way to combine validations:
+ * Validation<List<String>, Person> result3 =
+ *     Validation.combine(valid1, valid2, valid3).ap(f);
  * 
  * 
* - * @param value type in the case of invalid - * @param value type in the case of valid + * @param the type of values in the case of invalid + * @param the type of values in the case of valid * @author Eric Nelson - * @see Validation + * @see + * Scalaz Validation source */ public interface Validation extends Value, Serializable {