Skip to content

X Folding

John McClean edited this page Jul 26, 2018 · 6 revisions

Folds

Folds allow us to break apart the internal structure of a Cyclops data type and execute a function across it's contents. Some typical use cases include

  1. Executing an aggregation function across the contents of a Seq, Vector, ReactiveSeq or other non-scalar data structure
  2. Handling the case where an Option has Some value separately from where it has None.

Examples

Summing the contents of a List (Seq)

int res = Seq.of(1,2,3)
             .foldLeft(0,(a,b)->a+b);
//6

Handling Option.some and Option.none

int defaultValue = -1;
Option<Integer> none = Option.none();
int res = none.fold(some->some,()->defaultValue);
//-1 (defaultValue)

folding left and right

For non-scalar sequences Cyclops provides foldLeft and foldRight methods

  • foldLeft combines data in the sequence from left to right
  • foldRight combines data in the sequence from right to left (this is implemented lazily for LazySeq)

Lazy folds

To short circuit a la Haskell (see http://voidmainargs.blogspot.com/2011/08/folding-stream-with-scala.html)

foldr (||) False (repeat True)
True

we can make use of the combine operator on ReactiveSeq and lazyFoldRight on LazySeq.

With LazySeq

LazySeq.generate(()->true)
       .lazyFoldRight(false,(a, b)->a ? true : b.get());
//true

With ReactiveSeq

ReactiveSeq.generate(this::process)
           .map(data->data.isSuccess())
           .combine((a,b)-> a ? false : true, (a,b) -> a|b)
           .findFirst(); //terminating reduction on infinite data structure

The Folds interface

The Folds interface is implemented by a huge variety of data structures in Cyclops X (including all Persistent Collections, ReactiveSeq and Reactive Collections). Folds extends Iterable and has a large range of methods for processing the internal data of an implementing type to generate a new form.

Where the return type of the method Signature in Folds is a strict /eager type (such as Option) that indicates an eager / strict folding operation, where the return type of the method signature in Folds is a lazy / reactive tpye (such as Maybe) that indicates a lazy or reactive operation (where possible, this will depend if the implementing type is itself operating lazily or reactively).

Conversion methods

  • stream, toArray, bankersQueue, treeSet, hashSet, vector, lazySeq, seq, toHashMap, toMap, toCollection, toList, toSet
  • iterableTo - accepts a function to convert Folds to another form
  • groupBy - group the contents of the Object that implements Folds into a Persistent HashMap

Example iterableTo

ReactiveSeq<Integer> rs = LazySeq.of(1,2,3)
                                 .iterableTo(ReactiveSeq::fromIterable);

Statistical methods

Folding / reduce operations that perform some statistical function

  • count, countDistinct, maxBy, minBy, mode, occurances, mean, median, withPercentiles, atPercentile, variance ,populationVariance, stdDeviation, longStats, intStats , doubleStats ,maximum, minimum, sumInt , sumDouble, sumLong

Example atPercentile

ReactiveSeq.range(0,100)
           .atPercentile(0); //0

ReactiveSeq.range(0,100)
           .atPercentile(1); //1

ReactiveSeq.range(2,100)
           .atPercentile(2); //2

..

ReactiveSeq.range(0,100)
           .atPercentile(99); //99

Predicate methods

Folding / reduce methods that apply a predicate to the data and return a boolean value to indicate if it holds true.

  • xMatch, allMatch, anyMatch, noneMatch, startsWith, endsWith

Mutable Reduction

a la Java Streams

  • collect

Functional reduction

  • foldMap
  • foldLeft
  • foldRight
  • foldMapRight

String operations

  • join
  • print, printOut, printErr

Single Value extraction

  • headOption, firstValue ,singleOrElse, single, single, takeOne, elementAt

Index of operations

  • indexOf, lastIndexOf, indexOfSlice, lastIndexOfSlice

Scheduling emission

  • scheduleStream
Clone this wiki locally