javaslang.API Maven / Gradle / Ivy
/* / \____ _ _ ____ ______ / \ ____ __ _______
* / / \/ \ / \/ \ / /\__\/ // \/ \ // /\__\ JΛVΛSLΛNG
* _/ / /\ \ \/ / /\ \\__\\ \ // /\ \ /\\/ \ /__\ \ Copyright 2014-2016 Javaslang, http://javaslang.io
* /___/\_/ \_/\____/\_/ \_/\__\/__/\__\_/ \_// \__/\_____/ Licensed under the Apache License, Version 2.0
*/
package javaslang;
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\
G E N E R A T O R C R A F T E D
\*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
import static javaslang.API.Match.*;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import javaslang.collection.Iterator;
import javaslang.control.Option;
/**
* The most basic Javaslang functionality is accessed through this API class.
*
*
* import static javaslang.API.*;
*
*
* For-comprehension
*
* The {@code For}-comprehension is syntactic sugar for nested for-loops. We write
*
*
* // lazily evaluated
* Iterator<R> result = For(iterable1, iterable2, ..., iterableN).yield(f);
*
*
* or
*
*
* Iterator<R> result =
* For(iterable1, v1 ->
* For(iterable2, v2 ->
* ...
* For(iterableN).yield(vN -> f.apply(v1, v2, ..., vN))
* )
* );
*
*
* instead of
*
*
* for(T1 v1 : iterable1) {
* for (T2 v2 : iterable2) {
* ...
* for (TN vN : iterableN) {
* R result = f.apply(v1, v2, ..., VN);
* //
* // We are forced to perform side effects to do s.th. meaningful with the result.
* //
* }
* }
* }
*
*
* Please note that values like Option, Try, Future, etc. are also iterable.
*
* Given a suitable function
* f: {@code (v1, v2, ..., vN) -> ...} and 1 <= N <= 8 iterables, the result is a Stream of the
* mapped cross product elements.
*
*
* { f(v1, v2, ..., vN) | v1 ∈ iterable1, ... vN ∈ iterableN }
*
*
* As with all Javaslang Values, the result of a For-comprehension can be converted
* to standard Java library and Javaslang types.
* @author Daniel Dietrich
* @since 2.0.0
*/
public final class API {
private API() {
}
//
// Java type tweaks
//
/**
* Runs a {@code unit} of work and returns {@code Void}. This is helpful when a return value is expected,
* e.g. by {@code Match}:
*
* Match(i).of(
* Case(is(0), i -> run(() -> System.out.println("zero"))),
* Case(is(1), i -> run(() -> System.out.println("one"))),
* Case($(), o -> run(() -> System.out.println("many")))
* )
*
* @param unit A block of code to be run.
* @return the single instance of {@code Void}, namely {@code null}
*/
public static Void run(Runnable unit) {
unit.run();
return null;
}
//
// For-Comprehension
//
/**
* A shortcut for {@code Iterator.ofAll(ts).flatMap(f)} which allows us to write real for-comprehensions using
* {@code For(...).yield(...)}.
*
* Example:
*
* For(getPersons(), person ->
* For(person.getTweets(), tweet ->
* For(tweet.getReplies())
* .yield(reply -> person + ", " + tweet + ", " + reply)));
*
*
* @param ts An iterable
* @param f A function {@code T -> Iterable}
* @param element type of {@code ts}
* @param component type of the resulting {@code Iterator}
* @return A new Iterator
*/
public static Iterator For(Iterable ts, Function super T, ? extends Iterable> f) {
return Iterator.ofAll(ts).flatMap(f);
}
/**
* Creates a {@code For}-comprehension of one Iterable.
*
* @param ts1 the 1st Iterable
* @param component type of the 1st Iterable
* @return a new {@code For}-comprehension of arity 1
*/
public static For1 For(Iterable ts1) {
Objects.requireNonNull(ts1, "ts1 is null");
return new For1<>(ts1);
}
/**
* Creates a {@code For}-comprehension of two Iterables.
*
* @param ts1 the 1st Iterable
* @param ts2 the 2nd Iterable
* @param component type of the 1st Iterable
* @param component type of the 2nd Iterable
* @return a new {@code For}-comprehension of arity 2
*/
public static For2 For(Iterable ts1, Iterable ts2) {
Objects.requireNonNull(ts1, "ts1 is null");
Objects.requireNonNull(ts2, "ts2 is null");
return new For2<>(ts1, ts2);
}
/**
* Creates a {@code For}-comprehension of three Iterables.
*
* @param ts1 the 1st Iterable
* @param ts2 the 2nd Iterable
* @param ts3 the 3rd Iterable
* @param component type of the 1st Iterable
* @param component type of the 2nd Iterable
* @param component type of the 3rd Iterable
* @return a new {@code For}-comprehension of arity 3
*/
public static For3 For(Iterable ts1, Iterable ts2, Iterable ts3) {
Objects.requireNonNull(ts1, "ts1 is null");
Objects.requireNonNull(ts2, "ts2 is null");
Objects.requireNonNull(ts3, "ts3 is null");
return new For3<>(ts1, ts2, ts3);
}
/**
* Creates a {@code For}-comprehension of 4 Iterables.
*
* @param ts1 the 1st Iterable
* @param ts2 the 2nd Iterable
* @param ts3 the 3rd Iterable
* @param ts4 the 4th Iterable
* @param component type of the 1st Iterable
* @param component type of the 2nd Iterable
* @param component type of the 3rd Iterable
* @param component type of the 4th Iterable
* @return a new {@code For}-comprehension of arity 4
*/
public static For4 For(Iterable ts1, Iterable ts2, Iterable ts3, Iterable ts4) {
Objects.requireNonNull(ts1, "ts1 is null");
Objects.requireNonNull(ts2, "ts2 is null");
Objects.requireNonNull(ts3, "ts3 is null");
Objects.requireNonNull(ts4, "ts4 is null");
return new For4<>(ts1, ts2, ts3, ts4);
}
/**
* Creates a {@code For}-comprehension of 5 Iterables.
*
* @param ts1 the 1st Iterable
* @param ts2 the 2nd Iterable
* @param ts3 the 3rd Iterable
* @param ts4 the 4th Iterable
* @param ts5 the 5th Iterable
* @param component type of the 1st Iterable
* @param component type of the 2nd Iterable
* @param component type of the 3rd Iterable
* @param component type of the 4th Iterable
* @param component type of the 5th Iterable
* @return a new {@code For}-comprehension of arity 5
*/
public static For5 For(Iterable ts1, Iterable ts2, Iterable ts3, Iterable ts4, Iterable ts5) {
Objects.requireNonNull(ts1, "ts1 is null");
Objects.requireNonNull(ts2, "ts2 is null");
Objects.requireNonNull(ts3, "ts3 is null");
Objects.requireNonNull(ts4, "ts4 is null");
Objects.requireNonNull(ts5, "ts5 is null");
return new For5<>(ts1, ts2, ts3, ts4, ts5);
}
/**
* Creates a {@code For}-comprehension of 6 Iterables.
*
* @param ts1 the 1st Iterable
* @param ts2 the 2nd Iterable
* @param ts3 the 3rd Iterable
* @param ts4 the 4th Iterable
* @param ts5 the 5th Iterable
* @param ts6 the 6th Iterable
* @param component type of the 1st Iterable
* @param component type of the 2nd Iterable
* @param component type of the 3rd Iterable
* @param component type of the 4th Iterable
* @param component type of the 5th Iterable
* @param component type of the 6th Iterable
* @return a new {@code For}-comprehension of arity 6
*/
public static For6 For(Iterable ts1, Iterable ts2, Iterable ts3, Iterable ts4, Iterable ts5, Iterable ts6) {
Objects.requireNonNull(ts1, "ts1 is null");
Objects.requireNonNull(ts2, "ts2 is null");
Objects.requireNonNull(ts3, "ts3 is null");
Objects.requireNonNull(ts4, "ts4 is null");
Objects.requireNonNull(ts5, "ts5 is null");
Objects.requireNonNull(ts6, "ts6 is null");
return new For6<>(ts1, ts2, ts3, ts4, ts5, ts6);
}
/**
* Creates a {@code For}-comprehension of 7 Iterables.
*
* @param ts1 the 1st Iterable
* @param ts2 the 2nd Iterable
* @param ts3 the 3rd Iterable
* @param ts4 the 4th Iterable
* @param ts5 the 5th Iterable
* @param ts6 the 6th Iterable
* @param ts7 the 7th Iterable
* @param component type of the 1st Iterable
* @param component type of the 2nd Iterable
* @param component type of the 3rd Iterable
* @param component type of the 4th Iterable
* @param component type of the 5th Iterable
* @param component type of the 6th Iterable
* @param component type of the 7th Iterable
* @return a new {@code For}-comprehension of arity 7
*/
public static For7 For(Iterable ts1, Iterable ts2, Iterable ts3, Iterable ts4, Iterable ts5, Iterable ts6, Iterable ts7) {
Objects.requireNonNull(ts1, "ts1 is null");
Objects.requireNonNull(ts2, "ts2 is null");
Objects.requireNonNull(ts3, "ts3 is null");
Objects.requireNonNull(ts4, "ts4 is null");
Objects.requireNonNull(ts5, "ts5 is null");
Objects.requireNonNull(ts6, "ts6 is null");
Objects.requireNonNull(ts7, "ts7 is null");
return new For7<>(ts1, ts2, ts3, ts4, ts5, ts6, ts7);
}
/**
* Creates a {@code For}-comprehension of 8 Iterables.
*
* @param ts1 the 1st Iterable
* @param ts2 the 2nd Iterable
* @param ts3 the 3rd Iterable
* @param ts4 the 4th Iterable
* @param ts5 the 5th Iterable
* @param ts6 the 6th Iterable
* @param ts7 the 7th Iterable
* @param ts8 the 8th Iterable
* @param component type of the 1st Iterable
* @param component type of the 2nd Iterable
* @param component type of the 3rd Iterable
* @param component type of the 4th Iterable
* @param component type of the 5th Iterable
* @param component type of the 6th Iterable
* @param component type of the 7th Iterable
* @param component type of the 8th Iterable
* @return a new {@code For}-comprehension of arity 8
*/
public static For8 For(Iterable ts1, Iterable ts2, Iterable ts3, Iterable ts4, Iterable ts5, Iterable ts6, Iterable ts7, Iterable ts8) {
Objects.requireNonNull(ts1, "ts1 is null");
Objects.requireNonNull(ts2, "ts2 is null");
Objects.requireNonNull(ts3, "ts3 is null");
Objects.requireNonNull(ts4, "ts4 is null");
Objects.requireNonNull(ts5, "ts5 is null");
Objects.requireNonNull(ts6, "ts6 is null");
Objects.requireNonNull(ts7, "ts7 is null");
Objects.requireNonNull(ts8, "ts8 is null");
return new For8<>(ts1, ts2, ts3, ts4, ts5, ts6, ts7, ts8);
}
/**
* For-comprehension with one Iterable.
*/
public static class For1 {
private final Iterable ts1;
private For1(Iterable ts1) {
this.ts1 = ts1;
}
/**
* Yields a result for elements of the cross product of the underlying Iterables.
*
* @param f a function that maps an element of the cross product to a result
* @param type of the resulting {@code Iterator} elements
* @return an {@code Iterator} of mapped results
*/
public Iterator yield(Function super T1, ? extends R> f) {
Objects.requireNonNull(f, "f is null");
return Iterator.ofAll(ts1).map(f);
}
}
/**
* For-comprehension with two Iterables.
*/
public static class For2 {
private final Iterable ts1;
private final Iterable ts2;
private For2(Iterable ts1, Iterable ts2) {
this.ts1 = ts1;
this.ts2 = ts2;
}
/**
* Yields a result for elements of the cross product of the underlying Iterables.
*
* @param f a function that maps an element of the cross product to a result
* @param type of the resulting {@code Iterator} elements
* @return an {@code Iterator} of mapped results
*/
public Iterator yield(BiFunction super T1, ? super T2, ? extends R> f) {
Objects.requireNonNull(f, "f is null");
return
Iterator.ofAll(ts1).flatMap(t1 ->
Iterator.ofAll(ts2).map(t2 -> f.apply(t1, t2)));
}
}
/**
* For-comprehension with three Iterables.
*/
public static class For3 {
private final Iterable ts1;
private final Iterable ts2;
private final Iterable ts3;
private For3(Iterable ts1, Iterable ts2, Iterable ts3) {
this.ts1 = ts1;
this.ts2 = ts2;
this.ts3 = ts3;
}
/**
* Yields a result for elements of the cross product of the underlying Iterables.
*
* @param f a function that maps an element of the cross product to a result
* @param type of the resulting {@code Iterator} elements
* @return an {@code Iterator} of mapped results
*/
public Iterator yield(Function3 super T1, ? super T2, ? super T3, ? extends R> f) {
Objects.requireNonNull(f, "f is null");
return
Iterator.ofAll(ts1).flatMap(t1 ->
Iterator.ofAll(ts2).flatMap(t2 ->
Iterator.ofAll(ts3).map(t3 -> f.apply(t1, t2, t3))));
}
}
/**
* For-comprehension with 4 Iterables.
*/
public static class For4 {
private final Iterable ts1;
private final Iterable ts2;
private final Iterable ts3;
private final Iterable ts4;
private For4(Iterable ts1, Iterable ts2, Iterable ts3, Iterable ts4) {
this.ts1 = ts1;
this.ts2 = ts2;
this.ts3 = ts3;
this.ts4 = ts4;
}
/**
* Yields a result for elements of the cross product of the underlying Iterables.
*
* @param f a function that maps an element of the cross product to a result
* @param type of the resulting {@code Iterator} elements
* @return an {@code Iterator} of mapped results
*/
public Iterator yield(Function4 super T1, ? super T2, ? super T3, ? super T4, ? extends R> f) {
Objects.requireNonNull(f, "f is null");
return
Iterator.ofAll(ts1).flatMap(t1 ->
Iterator.ofAll(ts2).flatMap(t2 ->
Iterator.ofAll(ts3).flatMap(t3 ->
Iterator.ofAll(ts4).map(t4 -> f.apply(t1, t2, t3, t4)))));
}
}
/**
* For-comprehension with 5 Iterables.
*/
public static class For5 {
private final Iterable ts1;
private final Iterable ts2;
private final Iterable ts3;
private final Iterable ts4;
private final Iterable ts5;
private For5(Iterable ts1, Iterable ts2, Iterable ts3, Iterable ts4, Iterable ts5) {
this.ts1 = ts1;
this.ts2 = ts2;
this.ts3 = ts3;
this.ts4 = ts4;
this.ts5 = ts5;
}
/**
* Yields a result for elements of the cross product of the underlying Iterables.
*
* @param f a function that maps an element of the cross product to a result
* @param type of the resulting {@code Iterator} elements
* @return an {@code Iterator} of mapped results
*/
public Iterator yield(Function5 super T1, ? super T2, ? super T3, ? super T4, ? super T5, ? extends R> f) {
Objects.requireNonNull(f, "f is null");
return
Iterator.ofAll(ts1).flatMap(t1 ->
Iterator.ofAll(ts2).flatMap(t2 ->
Iterator.ofAll(ts3).flatMap(t3 ->
Iterator.ofAll(ts4).flatMap(t4 ->
Iterator.ofAll(ts5).map(t5 -> f.apply(t1, t2, t3, t4, t5))))));
}
}
/**
* For-comprehension with 6 Iterables.
*/
public static class For6 {
private final Iterable ts1;
private final Iterable ts2;
private final Iterable ts3;
private final Iterable ts4;
private final Iterable ts5;
private final Iterable ts6;
private For6(Iterable ts1, Iterable ts2, Iterable ts3, Iterable ts4, Iterable ts5, Iterable ts6) {
this.ts1 = ts1;
this.ts2 = ts2;
this.ts3 = ts3;
this.ts4 = ts4;
this.ts5 = ts5;
this.ts6 = ts6;
}
/**
* Yields a result for elements of the cross product of the underlying Iterables.
*
* @param f a function that maps an element of the cross product to a result
* @param type of the resulting {@code Iterator} elements
* @return an {@code Iterator} of mapped results
*/
public Iterator yield(Function6 super T1, ? super T2, ? super T3, ? super T4, ? super T5, ? super T6, ? extends R> f) {
Objects.requireNonNull(f, "f is null");
return
Iterator.ofAll(ts1).flatMap(t1 ->
Iterator.ofAll(ts2).flatMap(t2 ->
Iterator.ofAll(ts3).flatMap(t3 ->
Iterator.ofAll(ts4).flatMap(t4 ->
Iterator.ofAll(ts5).flatMap(t5 ->
Iterator.ofAll(ts6).map(t6 -> f.apply(t1, t2, t3, t4, t5, t6)))))));
}
}
/**
* For-comprehension with 7 Iterables.
*/
public static class For7 {
private final Iterable ts1;
private final Iterable ts2;
private final Iterable ts3;
private final Iterable ts4;
private final Iterable ts5;
private final Iterable ts6;
private final Iterable ts7;
private For7(Iterable ts1, Iterable ts2, Iterable ts3, Iterable ts4, Iterable ts5, Iterable ts6, Iterable ts7) {
this.ts1 = ts1;
this.ts2 = ts2;
this.ts3 = ts3;
this.ts4 = ts4;
this.ts5 = ts5;
this.ts6 = ts6;
this.ts7 = ts7;
}
/**
* Yields a result for elements of the cross product of the underlying Iterables.
*
* @param f a function that maps an element of the cross product to a result
* @param type of the resulting {@code Iterator} elements
* @return an {@code Iterator} of mapped results
*/
public Iterator yield(Function7 super T1, ? super T2, ? super T3, ? super T4, ? super T5, ? super T6, ? super T7, ? extends R> f) {
Objects.requireNonNull(f, "f is null");
return
Iterator.ofAll(ts1).flatMap(t1 ->
Iterator.ofAll(ts2).flatMap(t2 ->
Iterator.ofAll(ts3).flatMap(t3 ->
Iterator.ofAll(ts4).flatMap(t4 ->
Iterator.ofAll(ts5).flatMap(t5 ->
Iterator.ofAll(ts6).flatMap(t6 ->
Iterator.ofAll(ts7).map(t7 -> f.apply(t1, t2, t3, t4, t5, t6, t7))))))));
}
}
/**
* For-comprehension with 8 Iterables.
*/
public static class For8 {
private final Iterable ts1;
private final Iterable ts2;
private final Iterable ts3;
private final Iterable ts4;
private final Iterable ts5;
private final Iterable ts6;
private final Iterable ts7;
private final Iterable ts8;
private For8(Iterable ts1, Iterable ts2, Iterable ts3, Iterable ts4, Iterable ts5, Iterable ts6, Iterable ts7, Iterable ts8) {
this.ts1 = ts1;
this.ts2 = ts2;
this.ts3 = ts3;
this.ts4 = ts4;
this.ts5 = ts5;
this.ts6 = ts6;
this.ts7 = ts7;
this.ts8 = ts8;
}
/**
* Yields a result for elements of the cross product of the underlying Iterables.
*
* @param f a function that maps an element of the cross product to a result
* @param type of the resulting {@code Iterator} elements
* @return an {@code Iterator} of mapped results
*/
public Iterator yield(Function8 super T1, ? super T2, ? super T3, ? super T4, ? super T5, ? super T6, ? super T7, ? super T8, ? extends R> f) {
Objects.requireNonNull(f, "f is null");
return
Iterator.ofAll(ts1).flatMap(t1 ->
Iterator.ofAll(ts2).flatMap(t2 ->
Iterator.ofAll(ts3).flatMap(t3 ->
Iterator.ofAll(ts4).flatMap(t4 ->
Iterator.ofAll(ts5).flatMap(t5 ->
Iterator.ofAll(ts6).flatMap(t6 ->
Iterator.ofAll(ts7).flatMap(t7 ->
Iterator.ofAll(ts8).map(t8 -> f.apply(t1, t2, t3, t4, t5, t6, t7, t8)))))))));
}
}
//
// Structural Pattern Matching
//
// -- static Match API
/**
* Entry point of the match API.
*
* @param value a value to be matched
* @param type of the value
* @return a new {@code Match} instance
*/
public static Match Match(T value) {
return new Match<>(value);
}
// -- static Case API
// - Value
// Note: The signature ` Case Case(T value, $FunctionType super T, ? extends R> f)` leads to ambiguities!
public static Case Case(T value, Supplier extends R> supplier) {
Objects.requireNonNull(supplier, "supplier is null");
return new Case0<>($(value), ignored -> supplier.get());
}
public static Case Case(T value, R retVal) {
return new Case0<>($(value), ignored -> retVal);
}
// - Predicate
public static Case Case(Predicate super T> predicate, Function super T, ? extends R> f) {
Objects.requireNonNull(predicate, "predicate is null");
Objects.requireNonNull(f, "f is null");
return new Case0<>($(predicate), f);
}
public static Case Case(Predicate super T> predicate, Supplier extends R> supplier) {
Objects.requireNonNull(predicate, "predicate is null");
Objects.requireNonNull(supplier, "supplier is null");
return new Case0<>($(predicate), ignored -> supplier.get());
}
public static Case Case(Predicate super T> predicate, R retVal) {
Objects.requireNonNull(predicate, "predicate is null");
return new Case0<>($(predicate), ignored -> retVal);
}
// - Pattern0
public static Case Case(Pattern0 pattern, Function super T, ? extends R> f) {
Objects.requireNonNull(pattern, "pattern is null");
Objects.requireNonNull(f, "f is null");
return new Case0<>(pattern, f);
}
public static Case Case(Pattern0 pattern, Supplier extends R> supplier) {
Objects.requireNonNull(pattern, "pattern is null");
Objects.requireNonNull(supplier, "supplier is null");
return new Case0<>(pattern, ignored -> supplier.get());
}
public static Case Case(Pattern0 pattern, R retVal) {
Objects.requireNonNull(pattern, "pattern is null");
return new Case0<>(pattern, ignored -> retVal);
}
// - Pattern1
public static Case Case(Pattern1 pattern, Function super T1, ? extends R> f) {
Objects.requireNonNull(pattern, "pattern is null");
Objects.requireNonNull(f, "f is null");
return new Case1<>(pattern, f);
}
public static Case Case(Pattern1 pattern, Supplier extends R> supplier) {
Objects.requireNonNull(pattern, "pattern is null");
Objects.requireNonNull(supplier, "supplier is null");
return new Case1<>(pattern, _1 -> supplier.get());
}
public static Case Case(Pattern1 pattern, R retVal) {
Objects.requireNonNull(pattern, "pattern is null");
return new Case1<>(pattern, _1 -> retVal);
}
// - Pattern2
public static Case Case(Pattern2 pattern, BiFunction super T1, ? super T2, ? extends R> f) {
Objects.requireNonNull(pattern, "pattern is null");
Objects.requireNonNull(f, "f is null");
return new Case2<>(pattern, f);
}
public static Case Case(Pattern2 pattern, Supplier extends R> supplier) {
Objects.requireNonNull(pattern, "pattern is null");
Objects.requireNonNull(supplier, "supplier is null");
return new Case2<>(pattern, (_1, _2) -> supplier.get());
}
public static Case Case(Pattern2 pattern, R retVal) {
Objects.requireNonNull(pattern, "pattern is null");
return new Case2<>(pattern, (_1, _2) -> retVal);
}
// - Pattern3
public static Case Case(Pattern3 pattern, Function3 super T1, ? super T2, ? super T3, ? extends R> f) {
Objects.requireNonNull(pattern, "pattern is null");
Objects.requireNonNull(f, "f is null");
return new Case3<>(pattern, f);
}
public static Case Case(Pattern3 pattern, Supplier extends R> supplier) {
Objects.requireNonNull(pattern, "pattern is null");
Objects.requireNonNull(supplier, "supplier is null");
return new Case3<>(pattern, (_1, _2, _3) -> supplier.get());
}
public static Case Case(Pattern3 pattern, R retVal) {
Objects.requireNonNull(pattern, "pattern is null");
return new Case3<>(pattern, (_1, _2, _3) -> retVal);
}
// - Pattern4
public static