Cyclops X FINAL : Release version of Cyclops 10!
Cyclops X FINAL (10.0.0-FINAL)
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
- JVM polyglot higher kinder types support via KindedJ
What’s new Cyclops X FINAL Release
- API enhancement : remove limit / skip overloads (remains on ReactiveSeq for Stream compatibility)
- Recursion and concurrent Evaluation enhancements to Eval
- Performance enhancements : core operations improved for Vector, Seq, LazySeq
- Make illegal states unrepresentable : LazySeq is 100% lazy
- IO enhancements : synchronous IO and FutureStream based concurrent IO
API enhancement : remove limit / skip overloads
- take / drop are used everywhere
- only ReactiveSeq retains limit / skip as defined in the Stream API
Recursion and concurrent Evaluation enhancements to Eval
- Eval zipping should focus on supporting interleaving the execution of Evals
The zip method on Eval can used to Evaluate multiple lazy code blocks concurrently, and only accepts another Eval, Trampoline or Supplier as a parameter.
public void interleave(){
Eval<Integer> algorithm1 = loop(50000,Eval.now(5));
Eval<Integer> algorithm2 = loop2(50000,Eval.now(5));
//interleaved execution via Zip!
Tuple2<Integer, Integer> result = algorithm1.zip(algorithm2,Tuple::tuple).get();
System.out.println(result);
}
Eval<Integer> loop2(int times,Eval<Integer> sum){
System.out.println("Loop-B " + times + " : " + sum);
if(times==0)
return sum;
else
return sum.flatMap(s->loop2(times-1,Eval.now(s+times)));
}
Eval<Integer> loop(int times,Eval<Integer> sum){
System.out.println("Loop-A " + times + " : " + sum);
if(times==0)
return sum;
else
return sum.flatMap(s->loop(times-1,Eval.now(s+times)));
}
Producing output showing executing of interleaved lazy calls
Loop-B 15746 : Always[1126048874]
Loop-A 15745 : Always[1126064620]
Loop-B 15745 : Always[1126064620]
Loop-A 15744 : Always[1126080365]
Loop-B 15744 : Always[1126080365]
Loop-A 15743 : Always[1126096109]
Loop-B 15743 : Always[1126096109]
Loop-A 15742 : Always[1126111852]
Loop-B 15742 : Always[1126111852]
Loop-A 15741 : Always[1126127594]
Support Tail-recursion on methods that return a Supplier
Ensure a clean Eval can be created from a Supplier that supports tail-recursion on methods with JDK Friendly method signatures.
Supplier<Integer> loopSupplier(int times, int sum)
Then using Eval, this call shouldn't blow the stack
Supplier<Integer> algorithm1 = loopSupplier(50000,5);
System.out.println(algorithm1.get());
Provide a method to create an Eval from a Supplier
Supplier<Integer> loopSupplier(int times, int sum){
if(times==0)
return ()->sum;
else
return eval(()->sum).flatMap(s->Evala.eval(loopSupplier(times-1,s+times)));
}
Performance enhancements : core operations improved for Vector, Seq, LazySeq
Significant performance enhancements for append, get, setAt / update for core collections. E.g. Comparison with Vavr (post enhancements - Vavr was faster before) for Vector storing Strings
- Append 10,000 Strings 50th percentile (ms/ops) :
- Vector (Vavr) : 0.222
- Vector (Cyclops) : 0.041
https://github.com/aol/cyclops-react/blob/master/cyclops/src/jmh/java/cyclops/DataAppend.java
Make illegal states unrepresentable
** Make LazySeq totally lazy, solves numerous runtime errors and infinite loop issues
e.g. in Scala
Stream.continually(1)
.filter(i=>false)
.take(0)
.isEmpty //infinite loop that never finishes!
But Cyclops
LazySeq.generate(()->1)
.filter(I->false)
.take(0)
.isEmpty() //true!
IO enhancements : synchronous IO and FutureStream based concurrent IO
- Synchronous IO
For purely synchronous IO this model of execution will give better performance
IO.sync(this::readData)
.map(this::process)
.map(this::save)
.run()
- FutureStream based IO for blocking concurrent operations
FutureStreamIO.of(Executors.newCachedThreadPool(), this::readUserDataFromCache, this::readUserDataFromDisk, this::readUserDataFromDB)
.map(this::process)
.map(this::save)
.run()
Changelog
Check out the features delivered and bugs fixed -
github 10.0.0-FINAL issues & PRs
Dependency changes
Reactive Streams to 1.0.2
Modules
- cyclops - Persistent data structures and control types
- cyclops-futurestream - Parrallel asynchronous streaming
- cyclops-reactive-collections - Fast, non-blocking, asynchronous extensions for JDK and Persistent Collections
- cyclops-anyM - Higher kinded abstractions for working with any Java Monad type.
- cyclops-pure - Higher kinded type classes for pure functional programming in Java
- cyclops-reactor-integration - Reactive collections and AnyM integrations with Reactor.
- cyclops-rxjava2-integration - Reactive collections and AnyM integrations with Rx Java 2.
- cyclops-jackson-integration - Jackson databindings for Cyclops persistent data structures and control types.
Get cyclops X
Gradle
Cyclops
compile 'com.oath.cyclops:cyclops:10.0.0-FINAL’
Cyclops AnyM
compile 'com.oath.cyclops:cyclops-anym:10.0.0-FINAL’
Cyclops Futurestream
compile 'com.oath.cyclops:cyclops-futurestream:10.0.0-FINAL’
Cyclops Pure
compile 'com.oath.cyclops:cyclops-pure:10.0.0-FINAL’
Cyclops Reactive Collections
compile 'com.oath.cyclops:cyclops-reactive-collections:10.0.0-FINAL’
Cyclops Reactor Integration
compile 'com.oath.cyclops:cyclops-reactor-integration:10.0.0-FINAL'
Cyclops RxJava2 Integration
compile 'com.oath.cyclops:cyclops-rx2-integration:10.0.0-FINAL'
Cyclops Jackson Integration
compile 'com.oath.cyclops:cyclops-jackson-integration:10.0.0-FINAL'
Maven
Cyclops
<dependency>
<groupId>com.oath.cyclops</groupId>
<artifactId>cyclops</artifactId>
<version>10.0.0-FINAL</version>
</dependency>
Cyclops AnyM
<dependency>
<groupId>com.oath.cyclops</groupId>
<artifactId>cyclops-anym</artifactId>
<version>10.0.0-FINAL</version>
</dependency>
Cyclops Futurestream
<dependency>
<groupId>com.oath.cyclops</groupId>
<artifactId>cyclops-anym</artifactId>
<version>10.0.0-FINAL</version>
</dependency>
Cyclops Pure
<dependency>
<groupId>com.oath.cyclops</groupId>
<artifactId>cyclops-pure</artifactId>
<version>10.0.0-FINAL</version>
</dependency>
Cyclops Reactive Collections
<dependency>
<groupId>com.oath.cyclops</groupId>
<artifactId>cyclops-reactive-collections</artifactId>
<version>10.0.0-FINAL</version>
</dependency>
Cyclops Reactor Integration
<dependency>
<groupId>com.oath.cyclops</groupId>
<artifactId>cyclops-reactor-integration</artifactId>
<version>10.0.0-FINAL</version>
</dependency>
Cyclops RxJava2 Integration
<dependency>
<groupId>com.oath.cyclops</groupId>
<artifactId>cyclops-rx2-integration</artifactId>
<version>10.0.0-FINAL</version>
</dependency>
Cyclops Jackson Integration
<dependency>
<groupId>com.oath.cyclops</groupId>
<artifactId>cyclops-jackson-integration</artifactId>
<version>10.0.0-FINAL</version>
</dependency>
License
cyclops-react is licensed under the Apache 2.0 license.