Releases: aol/cyclops
Cyclops X - Milestone 1
Milestone one of Cyclops X
Cyclops X (cyclops 10) unifies cyclops-react and the cyclops integration modules on the cyclops versioning scheme. The goal of this project is remove a whole class of runtime errors from application code by providing much stricter APIs that prevent exceptional states from arising. A secondary goal is to modularize cyclops into a series of smaller more focused projects so that functionality is easy to find and developers only take what they need.
What’s new Cyclops X
-> Enhancements over cyclops-react 2
- Fast purely functional datastructures (Vector, Seq / List, LazySeq / LazyList, NonEmptyList, HashSet, TreeSet, TrieSet, HashMap, LinkedMap, MultiMap, TreeMap, BankersQueue, LazyString, Discrete Interval Encoded Tree, Zipper, Range, Tree, DifferenceList, HList, Dependent Map )
- Structural Pattern Matching API (deconstruct algebraic product and sum types)
- Improved type safety via the removal of unsafe APIs
-- E.g. Unlike Optional, Option has no get method (which could throw a null pointer)
-- New data structures do not support operations that would throw exceptions (you can't call head on an empty list for example) - Eager and Lazy alternatives for most datastructures (Option is eager, Maybe is lazy + reactive)
- Improved naming of types (Function1-8 rather than Fn1-8, Either not Xor)
- Group id is changed to com.oath.cyclops
- Versioning between cyclops-react and cyclops is merged on cyclops versioning scheme (version 10 = Cyclops X)
- Light weight dependencies : reactive-streams API & Agrona
Changelog
Check out the features delivered and bugs fixed -
Dependency changes
Cyclops no longer depends on pCollections or jOOλ
Get cyclops X
Gradle
compile 'com.oath.cyclops:cyclops:10.0.0-M1’
Maven
<dependency>
<groupId>com.oath.cyclops</groupId>
<artifactId>cyclops</artifactId>
<version>10.0.0-M1</version>
</dependency>
Documentation
Articles
- Reactive programming with Java 8 and simple-react: The Tutorial
- JDK Collection eXtensions
- Awesome Fluent Functions
- Straightforward Structural Pattern Matching
- Performant Functional Try
- Articles on medium
- Introducting the Cyclops Monad API
- Easier Try with Cyclops
- 4 flavors of Java 8 Functions
- Memoise Functions in Java 8
- Strategy Pattern in Java 8
- Functional Feature Toggling
- Dependency injection using the Reader Monad in Java8
- Scheduling a Stream
- Neophytes guide to Java 8 : Welcome to the Future
- Deterministic and Non-Deterministic Finite State Machines with Cyclops
License
cyclops-react is licensed under the Apache 2.0 license.
v2.1.1 of cyclops-react : Bug fixes and minor enhancements
2.1.1 of cyclops-react
What’s new cyclops-react v2.1.1
Various bug fixes.
- Fix bug in ListX.with method
- Eval.now filter issue
- Unlawful Groups removed
Enhancements
- JDK 9 Iterate methods for extended collections
- Kleisli for comprehensions
- Static tailRec methods on monad types
Changelog
Check out the features delivered and bugs fixed -
Dependency upgrades
None this time
Get cyclops-react
Gradle
compile 'com.aol.simplereact:cyclops-react:2.1.1’
Maven
<dependency>
<groupId>com.aol.simplereact</groupId>
<artifactId>cyclops-react</artifactId>
<version>2.1.1</version>
</dependency>
Documentation
Articles
- Reactive programming with Java 8 and simple-react: The Tutorial
- JDK Collection eXtensions
- Awesome Fluent Functions
- Straightforward Structural Pattern Matching
- Performant Functional Try
- Articles on medium
- Introducting the Cyclops Monad API
- Easier Try with Cyclops
- 4 flavors of Java 8 Functions
- Memoise Functions in Java 8
- Strategy Pattern in Java 8
- Functional Feature Toggling
- Dependency injection using the Reader Monad in Java8
- Scheduling a Stream
- Neophytes guide to Java 8 : Welcome to the Future
- Deterministic and Non-Deterministic Finite State Machines with Cyclops
License
cyclops-react is licensed under the Apache 2.0 license.
v2.1.0 of cyclops-react : Enhanced typeclasses, easier reactive-streams
2.1.0 of cyclops-react
What’s new cyclops-react v2.1.0
MonadRec typeclass
http://functorial.com/stack-safety-for-free/index.pdf Stack Safety for Free
MonadRec<maybe> mr = Maybe.Instances.monadRec();
Maybe<Integer> l = mr.tailRec(0, i -> i < 100_000 ? Maybe.just(Xor.secondary(i + 1)) : Maybe.just(Xor.primary(i + 1)))
.convert(Maybe::narrowK);
//Just[100_001];
Also available on Active
Active<list,Integer> list = ListX.of(1,2,3).allTypeclasses();
list.concreteTailRec(ListX.kindKleisli())
.tailRec(1,i-> 1<100_000 ? ListX.of(Xor.secondary(i+1)) : ListX.of(Xor.primary(i)));
//List[100_001]
Enumeration data type and enum Streaming support
ReactiveSeq.enums(Days.class)
.printOut();
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
Sunday
Enumeration.enums(Days.values())
.stream(Monday)
.join(" ")
//"Monday Tuesday Wednesday Thursday Friday Saturday Sunday"
Enumeration.enums(ListX.of(A,B,C,D,E,F,G,H,I,J))
.streamThenTo(A,C,G)
.join(" ");
"A C E G"
An effect type for composing side-effects
E.g. asycnhronously push data into an Observable style stream, cycling 30 times
Subscription sub = Spouts.asyncBufferBlock(10, s -> {
if (i == 0) {
Effect e = () -> {
s.onNext("hello " + i++);
};
e.cycle(30).runAsync();
}
}
).forEach(2, in->count++);
Buffering factory methods for reactive-streams and other async Stream types
reactiveBuffer creates a buffering reactive-streams Stream. User code can ignore incoming request information, this is managed by the buffering Stream. Pushed events are buffered before being sent downstream when requested. Users can set the overflow policy between block and drop.
Subscription sub = Spouts.reactiveBuffer(16, s -> {
s.onSubscribe(new Subscription() {
@Override
public void request(long n) {
if(i==0) {
Effect e = () -> {
s.onNext("hello " + i++);
};
e.cycle(30).runAsync();
}
}
@Override
public void cancel() {
}
});
}).forEach(2, in->count++);
//count will be 2, buffer will be 16
Thread.sleep(500);
sub.request(30);
assertThat(i,equalTo(30));
assertThat(count,equalTo(18));
Changelog
Check out the features delivered and bugs fixed -
Dependency upgrades
None this time
Get cyclops-react
Gradle
compile 'com.aol.simplereact:cyclops-react:2.1.0’
Maven
<dependency>
<groupId>com.aol.simplereact</groupId>
<artifactId>cyclops-react</artifactId>
<version>2.1.0</version>
</dependency>
Documentation
Articles
- Reactive programming with Java 8 and simple-react: The Tutorial
- JDK Collection eXtensions
- Awesome Fluent Functions
- Straightforward Structural Pattern Matching
- Performant Functional Try
- Articles on medium
- Introducting the Cyclops Monad API
- Easier Try with Cyclops
- 4 flavors of Java 8 Functions
- Memoise Functions in Java 8
- Strategy Pattern in Java 8
- Functional Feature Toggling
- Dependency injection using the Reader Monad in Java8
- Scheduling a Stream
- Neophytes guide to Java 8 : Welcome to the Future
- Deterministic and Non-Deterministic Finite State Machines with Cyclops
License
cyclops-react is licensed under the Apache 2.0 license.
v2.0.0-FINAL of cyclops-react
2.0.0-FINAL of cyclops-react
What’s new cyclops-react v2 - FINAL
Reactive Try
Try is now a Reactive data type, Try can operate eagerly (e.g. via Try.success, Try.failure,Try.withCatch, Try.runWithCatch), lazily (Try.fromIterable, Try.fromXor when an Either is used) or reactively (Try.fromPublisher or via toTry() on another reactive type).
A Reactive Try
ReactiveSeq<Integer> reactiveStream; //async populate a Stream with [1,2,3]
Try<Integer,Throwable> attempt = Try.fromPublisher(reactiveStream, RuntimeException.class);
Try<Integer,Throwable> doubled = attempt.map(i->i*2);
//when the data arrives doubled will be (first value from the Stream doubled)
//Try[2]
An Eager try
Try<Integer,Throwable> attempt = Try.success(1);
Try<Integer,Throwable> doubled = attempt.map(i->i*2);
//doubled will immediately be
//Try[2]
A lazy try
ReactiveSeq<Integer> reactiveStream = ReactiveSeq.of(1,2,3);
Try<Integer,Throwable> attempt = Try.fromIterable(stream);
Try<Integer,Throwable> doubled = attempt.map(i->i*2);
//doubled when accessed first will become
//Try[2]
Concurrency via Trampoline zip (& also in Free & Unrestricted)
Interleave execution of two looping algorithms
Trampoline<Integer> looping = loop(500000,5);
Trampoline<Integer> looping2 = loop2(500000,5);
System.out.println(looping.zip(looping2).get());
Trampoline<Integer> loop2(int times,int sum){
System.out.println("Loop-B " + times + " : " + sum);
if(times==0)
return Trampoline.done(sum);
else
return Trampoline.more(()->loop2(times-1,sum+times));
}
Trampoline<Integer> loop(int times,int sum){
System.out.println("Loop-A " + times + " : " + sum);
if(times==0)
return Trampoline.done(sum);
else
return Trampoline.more(()->loop(times-1,sum+times));
}
Prints
…
Loop-A 54 : 446196936
Loop-B 54 : 446196936
Loop-A 53 : 446196990
Loop-B 53 : 446196990
Loop-A 52 : 446197043
Loop-B 52 : 446197043
…
Concurrency via recursive data types
To execute two recursive algorithms simulatationously, convert to a Trampoline and zip!
public void odd(){
even(Maybe.just(200000)).toTrampoline()
.zip(odd1(Maybe.just(200000)).toTrampoline()).get();
}
public Maybe<String> odd(Maybe<Integer> n ) {
System.out.println("A");
return n.flatMap(x->even(Maybe.just(x-1)));
}
public Maybe<String> even(Maybe<Integer> n ) {
return n.flatMap(x->{
return x<=0 ? Maybe.just("done") : odd(Maybe.just(x-1));
});
}
public Maybe<String> odd1(Maybe<Integer> n ) {
System.out.println("B");
return n.flatMap(x->even1(Maybe.just(x-1)));
}
public Maybe<String> even1(Maybe<Integer> n ) {
return n.flatMap(x->{
return x<=0 ? Maybe.just("done") : odd1(Maybe.just(x-1));
});
}
Prints out
A
B
A
B
A
B
A
XorM and Coproduct
A Sum type for monads of the same type.
XorM / Coproduct are active type biased (rather than right biased).
e.g.
XorM<stream,optional,Integer> nums = XorM.stream(1,2,3)
.swap();
int result = nums.map(i->i*2)
.foldLeft(Monoids.intSum);
//12
}
Active and Nested data types
Active wraps a HKT encoding and any associated typeclasses to provide a fluent java friendly interface. Nested does the same for nested HKT encodings (e.g. an Optional inside a List)
Active<list,Integer> active = Active.of(ListX.of(1,2,3),ListX.Instances.definitions());
Active<list,Integer> doubled = active.map(i->i*2);
Active<list,Integer> doubledPlusOne = doubled.flatMap(i->ListX.of(i+1));
import cyclops.monads.Witness.list;
import cyclops.monads.Witness.optional;
Nested<list,optional,Integer> listOfOptionalInt = Nested.of(ListX.of(Optionals.OptionalKind.of(2)),ListX.Instances.definitions(),Optionals.Instances.definitions());
//Nested[List[Optional[2]]]
Nested<list,optional,Integer> listOfOptionalInt; //Nested[List[Optional[2]]]
Nested<list,optional,Integer> doubled = listOfOptionalInt.map(i->i*2);
//Nested[List[Optional[4]]]
Unfoldable type class
The unfoldable type class allows types to be recursively expanded (e.g. to generate a List from a function)
Unfoldable<list> unfoldable = ListX.Instances.unfoldable();
ListX<Integer> unfolded = unfoldable.unfold(1,i->i<=6 ? Optional.of(Tuple.tuple(i,i+1)) : Optional.empty());
//(1,2,3,4,5)
Yoneda, Coyoneda and Cofree data types
Coyoneda allows you use custom data types as if they were Functors with Free (without having to define a custom Functor), simplifying some of the machinery required to use the Free Monad.
Functor<Higher<Higher<coyoneda, Command>, Void>> commandFunctor = Coyoneda.functor();
val lifted = Free.liftF(new MyCommand<>(a, null), commandFunctor);
Changelog
Check out the features delivered and bugs fixed -
github 2.0.0-FINAL issues & PRs
github 2.0.0-RC8 issues & PRs
github 2.0.0-RC1 issues & PRs
Dependency upgrades
None this time
Get cyclops-react
Gradle
compile 'com.aol.simplereact:cyclops-react:2.0.0-FINAL’
Maven
<dependency>
<groupId>com.aol.simplereact</groupId>
<artifactId>cyclops-react</artifactId>
<version>2.0.0-FINAL</version>
</dependency>
Documentation
Articles
- Reactive programming with Java 8 and simple-react: The Tutorial
- JDK Collection eXtensions
- Awesome Fluent Functions
- Straightforward Structural Pattern Matching
- Performant Functional Try
- Articles on medium
- Introducting the Cyclops Monad API
- Easier Try with Cyclops
- 4 flavors of Java 8 Functions
- Memoise Functions in Java 8
- Strategy Pattern in Java 8
- Functional Feature Toggling
- Dependency injection using the Reader Monad in Java8
- Scheduling a Stream
- Neophytes guide to Java 8 : Welcome to the Future
- Deterministic and Non-Deterministic Finite State Machines with Cyclops
License
cyclops-react is licensed under the Apache 2.0 license.
v2.0.0-MI7 of cyclops-react
2.0.0-MI7 of cyclops-react
What’s new cyclops-react v2 Milestone 7?
- Kotlin style sequence generators
- Bug fixes
Some Examples
#e.g. with suspend and yield operators - note providing a BooleanSupplier indicates the suspended block should be executed until false (in this case infinitely).
int i = 100;
ReactiveSeq.generate(suspend(infinitely(),s->s.yield(i++)))
.take(6)
.printOut();
/**
100
101§
102
103
104
105
106
**/
Execute the suspended block just once (itself meaningless unless we can also sequence actions)
int i = 100;
ReactiveSeq.generate(suspend(s->s.yield(i++)))
.take(6)
.printOut();
/**
100
**/
Yield a sequence of values
ReactiveSeq.generate(suspend(times(10),s-> {
System.out.println("Top level - should repeat after sequence completes!");
return s.yield(1,
() -> s.yield(2),
() -> s.yield(3),
() -> s.yield(4));
}))
.take(6)
.printOut();
Support method references
Generator<Integer> generator = suspendRef(times(10),this::next);
generator.stream()
.forEach(System.out::println);
List<Integer> list = generator.to()
.linkedListX(LAZY)
.type(VavrTypes.list())
.map(this::process)
.to(VavrConverters::LIST);
public Integer next(){
return i++;
}
int i = 100;
Method references directly during yielding
ReactiveSeq.generate(suspend(times(10),s-> {
System.out.println("Top level - should repeat after sequence completes!");
return s.yieldRef(1,
Generator::next,
Generator::next,
Generator::next,
Generator::next);
}
)).take(6)
.printOut();
public Integer next(){
return i++;
}
More managable / complex mutable state via Inner Classes (if really needed)
ReactiveSeq.<Integer>generate(suspend(times(10),new ContFunction<Integer>() {
int runningTotal =0;
@Override
public Generator<Integer> apply(Suspended<Integer> s) {
System.out.println("Top level - should repeat after sequence completes!");
return s.yield(1,
() -> {
runningTotal = runningTotal +5;
return s.yield(runningTotal+2);
},
() -> s.yield(runningTotal+3),
() -> s.yield(runningTotal+6));
}
}
)).take(6)
.printOut();
Control looping based on current value and support safe (s.maybe()) and unsafe (s.current()) to the current value.
ReactiveSeq.generate(suspend((Integer i)->i==4,s-> {
System.out.println("Top level - repeat infinetely after sequence (because we return 4!)");
return s.yield(1,
() -> s.yield(s.maybe()
.map(o->o+5)
.orElse(10)),
() -> s.yield(s.current()),
() -> s.yield(4));
}
)).take(120)
.printOut();
Supporting nested generators would allow very fine control over generating data sources..
ReactiveSeq.generate(suspend((Integer i)->i!=4, s-> {
Generator<Integer> gen1 = suspend(times(5),
s2->s2.yield(i++));
Generator<Integer> gen2 = suspend(times(2),
s2->s2.yield(k--));
return s.yieldAll(gen1.stream(),
gen2.stream());
}
)).take(12)
.printOut();
Changelog
Check out the features delivered and bugs fixed -
Dependency upgrades
None this time
Get cyclops-react
Gradle
compile 'com.aol.simplereact:cyclops-react:2.0.0-MI7’
Maven
<dependency>
<groupId>com.aol.simplereact</groupId>
<artifactId>cyclops-react</artifactId>
<version>2.0.0-MI7</version>
</dependency>
Documentation
Articles
- Reactive programming with Java 8 and simple-react: The Tutorial
- JDK Collection eXtensions
- Awesome Fluent Functions
- Straightforward Structural Pattern Matching
- Performant Functional Try
- Articles on medium
- Introducting the Cyclops Monad API
- Easier Try with Cyclops
- 4 flavors of Java 8 Functions
- Memoise Functions in Java 8
- Strategy Pattern in Java 8
- Functional Feature Toggling
- Dependency injection using the Reader Monad in Java8
- Scheduling a Stream
- Neophytes guide to Java 8 : Welcome to the Future
- Deterministic and Non-Deterministic Finite State Machines with Cyclops
License
cyclops-react is licensed under the Apache 2.0 license.
v2.0.0-MI6 of cyclops-react
2.0.0-MI6 of cyclops-react
What’s new cyclops-react v2 Milestone 6?
- Xtended collections easy unwrapping and conversions
- Better 3rd party support for Xtended Collections
- API enhancements
- Package reorganization to make it easier to find features
- Unrestricted - a simplified version of Free
- AnyM retains reactive nature for reactive monads
- Easy conversion and extraction from Monad Transformers
- Other enhancements and bug fixes
Some Examples
Unwrapping Xtended types
LinkedList<Integer> list1 = ListX.of(1,2,3)
.toConverters::LinkedList);
3rd party support for Xtended Collections
VectorX<Integer> list1 = VectorX.of(1,2,3)
.type(VavrTypes.vector());
Changelog
Check out the features delivered and bugs fixed -
Dependency upgrades
None this time
Get cyclops-react
Gradle
compile 'com.aol.simplereact:cyclops-react:2.0.0-MI6’
Maven
<dependency>
<groupId>com.aol.simplereact</groupId>
<artifactId>cyclops-react</artifactId>
<version>2.0.0-MI6</version>
</dependency>
Documentation
Articles
- Reactive programming with Java 8 and simple-react: The Tutorial
- JDK Collection eXtensions
- Awesome Fluent Functions
- Straightforward Structural Pattern Matching
- Performant Functional Try
- Articles on medium
- Introducting the Cyclops Monad API
- Easier Try with Cyclops
- 4 flavors of Java 8 Functions
- Memoise Functions in Java 8
- Strategy Pattern in Java 8
- Functional Feature Toggling
- Dependency injection using the Reader Monad in Java8
- Scheduling a Stream
- Neophytes guide to Java 8 : Welcome to the Future
- Deterministic and Non-Deterministic Finite State Machines with Cyclops
License
cyclops-react is licensed under the Apache 2.0 license.
v2.0.0-MI5 of cyclops-react
2.0.0-MI5 of cyclops-react
What’s new cyclops-react v2 Milestone 5?
- Asynchronous caching for Functions
- Performance improvement for combinations
- More efficient use of Queues in FutureStreams
- Other enhancements and bug fixes
Changelog
Check out the features delivered and bugs fixed -
Dependency upgrades
None this time
Get cyclops-react
Gradle
compile 'com.aol.simplereact:cyclops-react:2.0.0-MI5’
Maven
<dependency>
<groupId>com.aol.simplereact</groupId>
<artifactId>cyclops-react</artifactId>
<version>2.0.0-MI5</version>
</dependency>
Documentation
Articles
- Reactive programming with Java 8 and simple-react: The Tutorial
- JDK Collection eXtensions
- Awesome Fluent Functions
- Straightforward Structural Pattern Matching
- Performant Functional Try
- Articles on medium
- Introducting the Cyclops Monad API
- Easier Try with Cyclops
- 4 flavors of Java 8 Functions
- Memoise Functions in Java 8
- Strategy Pattern in Java 8
- Functional Feature Toggling
- Dependency injection using the Reader Monad in Java8
- Scheduling a Stream
- Neophytes guide to Java 8 : Welcome to the Future
- Deterministic and Non-Deterministic Finite State Machines with Cyclops
License
cyclops-react is licensed under the Apache 2.0 license.
v2.0.0-MI4 of cyclops-react - Kleisli and new Monad types
2.0.0-MI4 of cyclops-react
What’s new cyclops-react v2 Milestone 4?
New Monads and types for working with Monads
- Kleisli
- Cokleisli
- Writer
- State
- ReaderWriterState
Kleisli example
Define a function that creates a Stream
import cyclops.monads.Witness.reactiveSeq;
Kleisli<reactiveSeq, Integer, Integer> k1 = t -> ReactiveSeq.iterate(0,i->i<t, i->i+1)
.anyM();
k1.flatMap(i-> t-> ReactiveSeq.of(t+i)
.anyM())
.apply(10)
.forEach(System.out::println);
10
11
12
13
14
15
16
17
18
19
Changelog
Check out the features delivered and bugs fixed -
Dependency upgrades
None this time
Get cyclops-react
Gradle
compile 'com.aol.simplereact:cyclops-react:2.0.0-MI4’
Maven
<dependency>
<groupId>com.aol.simplereact</groupId>
<artifactId>cyclops-react</artifactId>
<version>2.0.0-MI4</version>
</dependency>
Documentation
Articles
- Reactive programming with Java 8 and simple-react: The Tutorial
- JDK Collection eXtensions
- Awesome Fluent Functions
- Straightforward Structural Pattern Matching
- Performant Functional Try
- Articles on medium
- Introducting the Cyclops Monad API
- Easier Try with Cyclops
- 4 flavors of Java 8 Functions
- Memoise Functions in Java 8
- Strategy Pattern in Java 8
- Functional Feature Toggling
- Dependency injection using the Reader Monad in Java8
- Scheduling a Stream
- Neophytes guide to Java 8 : Welcome to the Future
- Deterministic and Non-Deterministic Finite State Machines with Cyclops
License
cyclops-react is licensed under the Apache 2.0 license.
v2.0.0-MI3 of cyclops-react : More reactive types and Streams
2.0.0-MI3 of cyclops-react
What’s new cyclops-react v2 Milestone 3?
MI3 of v2 introduces a new push based / event driven ReactiveSeq implementation. Push based Streams can be created via the Spouts Factory class and can operate either in non-blocking Backpressure aware (reactive-streams) or back pressure free mode.
In addition core cyclops-react functional types including :- Maybe, Either, Either3, Either4, Either5, Eval, ListX, SetX, SortedSetX, QueueX, DequeX, PStackX, PVectorX, PSetX, POrderedSetX, PQueueX, PBagX can all operate as non-blocking reactive types (alongside Future and FutureStream).
A host of new operators have been added including : fanOut, parallelFanOut, Java 9 style iterate, deferred, ofNullable, multicast, broadcast, publishTo, changes, ambWith, findOne, firstOrError and more.
New types introduced include MaybeT, OptionalT, EvalT, CompletableFutureT, StreamT type safe, higher kinded monad transformers
- ReactiveSeq supports non-blocking push based Streams
ReactiveSeq<Integer> input = Spouts.async(subscriber->{
listener.onEvent(subscriber::onNext);
listener.onError(susbscriber::onError);
closeListener.onEvent(subscriber::onClose);
});
input.map(this::process)
.forEach(this::handleResult,this::handleError,this::finish);
- And non-blocking backpressure via reactive-streams for asynchronous and synchronous Streams
ReactiveSeq<Integer> input = Spouts.publishOn(ReactiveSeq.of(1,2,3),
Executors.newFixedThreadPool(1));
Subscription sub = input.map(this::process)
.subscribe(this::handleResult,this::handleError,this::finish);
sub.request(2);
- An array of non-blocking Reactive Types
Collections
ReactiveSeq<Integer> input = Spouts.publishOn(ReactiveSeq.of(1,2,3),
Executors.newFixedThreadPool(1));
ListX<Integer> res = input.map(this::process)
.toListX();
this.continueProcessing();
currentThreadIsNotBlocked();
Integer thisBlocksThough = res.get(5);
//ListX, SetX, DequeX, QueueX, QueueX and persistent analogs populated asynchronously, without blocking the current Thread
Maybe
ReactiveSeq<Integer> input = Spouts.publishOn(ReactiveSeq.of(1,2,3),
Executors.newFixedThreadPool(1));
Maybe<Integer> res = input.map(this::process)
.findOne();
//Maybe populated asynchronously and without blocking the current thread.
Either
ReactiveSeq<Integer> input = Spouts.publishOn(ReactiveSeq.of(1,2,3),
Executors.newFixedThreadPool(1));
Either<Throwable,Integer> = input.map(this::process)
.findFirstOrError();
//Either populated asynchronously and without blocking the current thread.
And more!
Eval, Either3-5, ListX,SetX,QueueX,DequeX,SortedSetX,PStackX,PVectorX,PQueueX,PSetX,POrderedSetX,PBagX
Completable Types
2.0.0-MI3 introduces CompletableMaybe, CompletableEval and CompletableEither(3-5).
Completable types allow a dataflow to be defined and completed asynchronously.
//create a CompletableEither
CompletableEither<Integer,Integer> completable = Either.either();
//define the data flow
Either<Throwable,Integer> mapped = completable.map(i->i*2)
.flatMap(i->Eval.later(()->i+1));
//potentially asynchronously / on another thread push a value into the Either
completable.complete(5);
//execute the dataflow and printout
mapped.printOut();
assertThat(mapped.get(),equalTo(11));
//or connect to another reactive type asynchronously
Spouts.from(mapped)
.forEach(this::continueProcessing,this::handleErrors);
Changelog
Check out the features delivered and bugs fixed -
Dependency upgrades
None this time
Get cyclops-react
Gradle
compile 'com.aol.simplereact:cyclops-react:2.0.0-MI3’
Maven
<dependency>
<groupId>com.aol.simplereact</groupId>
<artifactId>cyclops-react</artifactId>
<version>2.0.0-MI3</version>
</dependency>
Documentation
Articles
- Reactive programming with Java 8 and simple-react: The Tutorial
- JDK Collection eXtensions
- Awesome Fluent Functions
- Straightforward Structural Pattern Matching
- Performant Functional Try
- Articles on medium
- Introducting the Cyclops Monad API
- Easier Try with Cyclops
- 4 flavors of Java 8 Functions
- Memoise Functions in Java 8
- Strategy Pattern in Java 8
- Functional Feature Toggling
- Dependency injection using the Reader Monad in Java8
- Scheduling a Stream
- Neophytes guide to Java 8 : Welcome to the Future
- Deterministic and Non-Deterministic Finite State Machines with Cyclops
License
cyclops-react is licensed under the Apache 2.0 license.
v2.0.0-MI1 of cyclops-react
2.0.0-MI1 of cyclops-react
What’s new cyclops-react v2?
- ReactiveSeq is replayable
ReactiveSeq<Integer> range = ReactiveSeq.range(0,1);
range.forEach(System.out::println);
range.map(this::process).forEach(System.out::println);
- Collections are lazy
ListX<Data> load = ListX.of(1,2,3)
.map(i->i*2)
.filter(i->i<3)
.map(this::lookup);
Unlike most other functional style collection implementations load is a lazy refernce and the dataflow is only executed (once) on initial access. This gives much better performance for chained dataflows as the collection is traversed only once.
- Streaming engine behind ReactiveSeq rewritten from scratch to be both replayable and ultra-efficient
- Parralel sections within a sequential Stream
ReactiveSeq.generate(this::nextValue)
.map(this::process)
.parallel(new ForkJoinPool(10),
par->par.map(this::cpuIntensiveOp)
.filter(this::accept))
.forEach(this::store);
The parallel section is executed in parallel, the rest executed sequentially
- Free Monad implementation for functional interpreters
- Type safe, higher kinded AnyM implementation using Witness types
AnyM<optional,Integer> opt = by2(AnyM.ofNullable(10));
AnyM<stream,Integer> stream = by2(AnyM.fromArray(10,20,30));
Stream<Integer> rawStream = stream.to(Witness::stream);
Optional<Integer> rawOptional = opt.to(Witness::optional);
public <W extends WitnessType<W>> AnyM<W,Integer> by2(AnyM<W,Integer> toMultiply){
return toMultiply.map(i->i*2);
}
- Lazy tail recursive Either implementations (Either through Either5)
- Higher kinded types for core cyclops-react types
- Higher kinded type classes fro core cyclops-react types
- Interface rationalization - more focused types, better naming
e.g. LazyFutureStream becomes FutureStream
Still to come (work in progress)
- Pure push sequential ReactiveSeq implementation
ReactiveSubscriber<Integer> pushable = ReactiveSeq.pushable();
ReactiveSeq<Integer> stream = pushable.stream();
stream.map(i->i*2)
.forEach(System.out::println);
pushable.onNext(10);
//20
See cyclops.StreamSource to push data into pull based sequential Streams.
Changelog
Check out the features delivered and bugs fixed -
Dependency upgrades
Agrona to 0.9.1
Jooλ to 0.9.12
Get cyclops-react
Gradle
compile 'com.aol.simplereact:cyclops-react:2.0.0-MI1’
Maven
<dependency>
<groupId>com.aol.simplereact</groupId>
<artifactId>cyclops-react</artifactId>
<version>2.0.0-MI1</version>
</dependency>
Documentation
Articles
- Reactive programming with Java 8 and simple-react: The Tutorial
- JDK Collection eXtensions
- Awesome Fluent Functions
- Straightforward Structural Pattern Matching
- Performant Functional Try
- Articles on medium
- Introducting the Cyclops Monad API
- Easier Try with Cyclops
- 4 flavors of Java 8 Functions
- Memoise Functions in Java 8
- Strategy Pattern in Java 8
- Functional Feature Toggling
- Dependency injection using the Reader Monad in Java8
- Scheduling a Stream
- Neophytes guide to Java 8 : Welcome to the Future
- Deterministic and Non-Deterministic Finite State Machines with Cyclops
License
cyclops-react is licensed under the Apache 2.0 license.