-
Notifications
You must be signed in to change notification settings - Fork 136
For
The For class in cyclops-react provides access to a For Comprehension interpreter, with a set of builders For comprehensions for Publishers, Values and access to the lower level Do builder for other types (iterable, reader, future, optional, Stream anyM).
More efficient type specific For Comprehensions are available directly on cyclops-react types via forEach2, forEach3, forEach4 etc.
For allows us to simplify deeply nested map / flatMap operations. One specialization that this covers is the simplification of nested loops (as we can loop through every element in two lists by flatMapping the first list, and mapping over the second list inside that flatMap operation). But For Comprehensions can be used everywhere you find yourself nesting flatMap and map operations.
## Examples
Imagine we have a Person class
class Person{
public String getName();
public Maybe<Address> getAddress();
}
class Address{
public Maybe<ZipCode> getZip();
}
If we want to extract the persons name and zip, but only where the zip is present we could make use of Maybe#flatMap. With for comprehensions this becomes neater
import static com.aol.cyclops.control.For.Values.each2;
String nameAndZip = each2(person::getAddress,
Address:getZip,
(person,zip)-> "Name:" + person.getName()
+ "\nzip" + zip)
.orElse("N/A");
We can perform a For comprehension with a Filter over a Flux type (from Pivotal's Reactor project) and a cyclops-react ReactiveSeq. This will visit every element of both Streams. In this example we will filter out any combination where the total is less than 10.
import static com.aol.cyclops.control.For.Publishers.each2;
ListX<Tuple2<Integer,Integer>> list;
list = each2(Flux.range(1,10),
i-> ReactiveSeq.iterate(i,a->a+1)
.limit(10),
(a,b)->a+b<10,
Tuple::tuple)
.toListX();
Ultimately this is syntax sugar for the code below, where we perform a nested map operation inside a flatMap operation.
ListX<Tuple2<Integer,Integer>> list2;
list2 = Flux.range(1,10)
.flatMap(i-> ReactiveSeq.iterate(i,a->a+1)
.limit(10)
.filter(a->i+a<10)
.map(a->Tuple.tuple(i,a)))
.toList()
.block();
assertThat(list,equalTo(list2));
With For.Publishers we can execute For comprehensions, that perform nested loops over any Publisher type.
import org.jooq.lambda.tuple.Tuple;
import org.jooq.lambda.tuple.Tuple4;
import static com.aol.cyclops.control.For.Publishers.each4;
ListX<Tuple4<Integer,Integer,Integer,Integer>> list;
list = each4(Flux.range(1,10),
a-> ReactiveSeq.iterate(a,i->i+1).limit(10),
(a,b) -> Maybe.<Integer>of(a+b),
(a,b,c) -> Mono.<Integer>just(a+b+c),
Tuple::tuple)
.toListX();
The return type of For operations is a monad wrapper AnyM for more details on how to use AnyM and extract it's values see this page AnyM intro.
oops - my bad