Skip to content

Cyclops X Milestone 6 : Reactive Collections

Compare
Choose a tag to compare
@johnmcclean johnmcclean released this 11 Mar 00:00
· 509 commits to master since this release
5548827

Milestone 6 of Cyclops X

Cyclops-reactive-collections is the last module to be created for Cyclops X (released in Milestone 6). Cyclops lazy and reactive extended collection types move out of the core into their own module, where they can be configured to run powered by Cyclops’ ReactiveSeq or by asynchronous streams in RxJava/2 or Pivotal’s Reactor.

Cyclops Reactive Collections are a suite of extensions for JDK and Persistent Collection types that support a large range of operators as well as (smart) lazy execution of chained operators to drive performance and asynchronous data flows through those operators.

As well as providing configuration options for the reactive engine powering the collections, it is possible to configure the collection types used. E.g. we can switch between Cyclops persistent collections or Vavr persistent collections.

The core of cyclops has been refactored to use Cyclops’ own eager persistent data structures (such as Vector, Seq and LazySeq).

Other improvements in this release include

  • Integration with KindedJ which provides a standard interface for simulated Higher Kinded types on the JVM (also used in the Arrow library for Kotlin)
  • A much enhanced LazyString implementation
  • More consistent naming of grouped and append method suites
  • cyclops-pure refactored to use cyclops persistent data types rather than extended collections
  • AnyM based monad transformers for core Cyclops Data types (OptionT, VectorT, LazySeqT, SeqT)

Enhanced performance via laziness

Chaining combinator operations on traditional functional datastructures such as the core persistent data structures provided in cyclops.data (or in Vavr or the Scala SDK) results in traversing the datastructure multiple times, once per combinator operation.

E.g. to transform and filter a Cyclops Vector we could write code like the following

Vector.of(1,2,3)
      .map(i->i*100)
      .filter(i->i<200);

Each of the chained operations will traverse the Vector, once for map and once for filter.

With Cyclops Reactive Collections VectorX the code remains very similar, the underlying datastructure remains identical, but the performance is much improved

VectorX.of(1,2,3)
       .map(i->i*100)
       .filter(i->i<200);

VectorX in contrast to a raw Vector traverses the underlying data structure just once.

Performance improvement for Vavr's Vector when used with Cyclops VectorX

Lower score is better

  • Raw Vavr Vector is on the Right.
  • Vavr Vector with Cyclops VectorX is on the left.

screen shot 2018-03-01 at 15 14 43

Reactive Collections!

In the example below we asynchronously populate an Xtended list using an asynchronously executing ReactiveSeq. Additional reactive operations can be performed on the List asynchronously.
The ListX only blocks on first access to the data.

AtomicBoolean complete = new AtomicBoolean(false);


ReactiveSeq<Integer> async =  Spouts.async(ReactiveSeq.of(1,2,3),Executors.newFixedThreadPool(1));

ListX<Integer> asyncList = ListX.listX(async)
                                   .map(i->i+1);

System.out.println("Blocked? " + complete.get());

System.out.println("First value is "  + asyncList.get(0));

System.out.println("Completed? " + complete.get());

Which will print

Blocked? false
First value is 101
Completed? true

Available data structures

cyclops.collections (mutable / immutable)

type description characteristics
ListX Functional extensions for working with Lists Optionally Reactive or Coreactive, Lazy, mutable, immutable, 3rd party support, Higher kinded
DequeX Functional extensions for working with Deques Optionally Reactive or Coreactive, Lazy, mutable, immutable, 3rd party support, Higher kinded
QueueX Functional extensions for working with Queues Optionally Reactive or Coreactive, Lazy, mutable, immutable, 3rd party support, Higher kinded
SetX Functional extensions for working with Sets Optionally Reactive or Coreactive, Lazy , mutable, immutable, 3rd party support
SortedSetX Functional extensions for working with SortedSets Optionally Reactive or Coreactive, Lazy, mutable, immutable
MapX Functional extensions for working with Maps Eager, mutable, immutable

cyclops.collections.persistent

type description characteristics
LinkedListX Functional extensions for working with persistent Lists Optionally Reactive or Coreactive, Lazy, persistent, 3rd party support, Higher kinded
VectorX Functional extensions for working with persistent Vectors Optionally Reactive or Coreactive, Lazy, persistent, 3rd party support, Higher kinded
PersistentSetX Functional extensions for working with persistent Sets Optionally Reactive or Coreactive, Lazy, persistent, 3rd party support
OrderedSetX Functional extensions for working with persistent Ordered Sets Optionally Reactive or Coreactive, Lazy, persistent, 3rd party support
PersistentQueueX Functional extensions for working with persistent Queues Optionally Reactive or Coreactive, Lazy, persistent, 3rd party support, Higher kinded
BagX Functional extensions for working with persistent Bags (set like collections that allow duplicates) Optionally Reactive or Coreactive,Lazy, persistent, 3rd party support

Examples

Lazy execution using extended Collections

Eval<Integer> lazyResult = ListX.of(1,2,3,4)
                                 .map(i->i*10)
                                 .foldLazy(s->s
                                 .reduce( 50,(acc,next) -> acc+next));

Articles

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

What’s new Cyclops X Milestone 5

  • Pure functional programming Module
  • flatMap and map Operators on Trampoline
  • reactive-streams based IO Monad
  • Safe PartialFunction API

Changelog

Check out the features delivered and bugs fixed -

github 10.0.0-M6 issues & PRs

Dependency changes

Cyclops no longer depends on pCollections or jOOλ

Get cyclops X

Gradle

Cyclops

compile 'com.oath.cyclops:cyclops:10.0.0-M6’

Cyclops AnyM

compile 'com.oath.cyclops:cyclops-anym:10.0.0-M6’

Cyclops Futurestream

compile 'com.oath.cyclops:cyclops-futurestream:10.0.0-M6’

Cyclops Pure

compile 'com.oath.cyclops:cyclops-pure:10.0.0-M6’

Cyclops Reactive Collections

compile 'com.oath.cyclops:cyclops-reactive-collections:10.0.0-M6’

Maven

Cyclops

<dependency>
    <groupId>com.oath.cyclops</groupId>
    <artifactId>cyclops</artifactId>
    <version>10.0.0-M6</version>
</dependency>

Cyclops AnyM

<dependency>
    <groupId>com.oath.cyclops</groupId>
    <artifactId>cyclops-anym</artifactId>
    <version>10.0.0-M6</version>
</dependency>

Cyclops Futurestream

<dependency>
    <groupId>com.oath.cyclops</groupId>
    <artifactId>cyclops-anym</artifactId>
    <version>10.0.0-M6</version>
</dependency>

Cyclops Pure

<dependency>
    <groupId>com.oath.cyclops</groupId>
    <artifactId>cyclops-pure</artifactId>
    <version>10.0.0-M6</version>
</dependency>

Cyclops Reactive Collections

<dependency>
    <groupId>com.oath.cyclops</groupId>
    <artifactId>cyclops-reactive-collections</artifactId>
    <version>10.0.0-M6</version>
</dependency>

Documentation

Articles

Old simple-react landing page

License

cyclops-react is licensed under the Apache 2.0 license.

http://www.apache.org/licenses/LICENSE-2.0#