Reactive Polyglot Save

FRP libraries / langs compared

Project README

Reactive polyglot

R. (Ramda) stands for standard functional toolkit.

Comparison notes

Operator counterparts aren't and can't be fully equivalent.
"Kinda the same" – is the current definition.

The following projects, were created with different goals and tradeoffs in mind, so every comparison and analogy is subjective and can be argued. The presence of some operator is not necessary good, as well as the abscence is not necessary bad.

Note, that primitives differ for each library. In descriptions, we broadly refer to all the "observable primitives" as streams*, though, technically speaking, some of them are rather stream-like entities.

To find something, search for a term you know.

API

Create

Create an empty stream

Create a stream from a single value

Create a stream from an array

Create a stream from a promise

Create a stream from an event

Create a stream from a callback

Prepend a stream with a value

Transform (data events)

Map value one-to-one

  • KefirJS: map
  • MostJS: map, constant
  • RxJS: map, mapTo
  • XStream: map

Filter value by a predicate

  • KefirJS: filter
  • MostJS: filter
  • RxJS: filter
  • XStream: filter

Skip N initial values

  • KefirJS: skip
  • MostJS: skip
  • RxJS: skip
  • XStream: drop

Take N initial values

  • KefirJS: take
  • MostJS: take
  • RxJS: take
  • XStream: take

Make a value from an accumulator and a next value

  • KefirJS: scan
  • MostJS: scan
  • RxJS: scan
  • XStream: fold

Combine

Merge multiple streams together

  • KefirJS: merge
  • MostJS: merge
  • RxJS: merge
  • XStream: merge

Pay attention that Kefir's merge accepts arrays while others are variadic.

Combine multiple streams together

Sample a stream by another stream

Chain streams sequentially


Create

Create stream from non-stream values.

KefirJS MostJS RxJS XStream
interval periodic interval + map periodic
repeat of + R.range repeat of + R.range
? iterate generate ?
? generate generate ?

Mapper

Modify events one to one.

KefirJS MostJS RxJS XStream
delay delay delay combine(delay(500))
– (map) timestamp timestamp – (map)

Transforms

Modify events * to *.

MostJS RxJS XStream
chain / flatMap flatMap map + flattenConcurrently
map + switch switchMap / flatMapLatest map + flatten
join mergeAll flatten
loop scan + map fold + map
– (custom) bufferWithCount ?

Filters

Skip events by predicate or signal.

MostJS RxJS XStream
skipRepeats distinctUntilChanged dropRepeats
skipRepeatsWith – (scan) dropRepeats
slice skip + take drop + take
skipWhile skipWhile fold + filter + map
takeWhile takeWhile filter + endWhen
since / skipUntil skipUntil fold + filter + map
until / takeUntil takeUntil filter + endWhen
during window + take(1) ?

Combinators

Combine multiple streams into single.

MostJS RxJS XStream
zip zip ?
concat concat concat
ap combineLatest ?

Side effects

Produce side effect for every event.

MostJS RxJS XStream
tap do / tap debug

Ending

Operators which target end event somehow.

MostJS RxJS XStream
empty empty empty
never never never
continueWith ? concat

Concurrency

MostJS RxJS
– (custom) amb / race

History

MostJS RxJS
– (custom)

Design diffs

RxJS

  1. Three primitives: Observer, Observable, Subject.
  2. Observables end on error.
  3. Provides API to handle errors.
  4. Does not provide API to handle ending.

KefirJS

  1. Two primitives: Stream and Property (like XStream).
  2. Observables does not end on error (by default).
  3. Provides API to handle errors.
  4. Provides API to handle ending.

MostJS

  1. One primitive: Stream (+ community-driven).
  2. Separate packages for subject-like and property-like primitives.
  3. Provides API to handle errors.
  4. Provides API to handle ending.

XStream

  1. Two primitives: Stream and MemoryStream (like KefirJS).
  2. Always multicast. A Stream is like an RxJS Subject.
  3. Streams end on error.

Common

RxJS does not emit initial scan value as event (use startWith for that).

Rx.Observable.interval(100).map(x => 1)
  .scan(add, 0);
  .subscribe(console.log); // 1--2--3--...

Most.periodic(100, 1)
  .scan(add, 0);
  .observe(console.log); // 0--1--2--3--...

Found docs / API quirks

MostJS

startWith vs sampleWith vs continueWith + recoverWith vs skipRepeatsWith
(val vs none vs func vs stream)

tap is listed in "Transform" section.

RxJS

startWith is listed in "Combine" section.

mergeAll is listed in "Combine" section.

distinct is not listed in "Filtering" section.

takeUntil is not listed in "Filtering" section.

just / return should be deprecated in favor of of.

fromArray should be deprecated in favor of from.

bacon-vs-kefir – BaconJS vs KefirJS API comparison

dataflows – web arch. dataflow comparison

stream-conversions – tool for cross-library stream conversions

Additional Read

https://github.com/cujojs/most/issues/171

https://twitter.com/rpominov/status/689566111734599683

https://github.com/zenparsing/es-observable/issues/66

Reactive polyglot

R. (Ramda) stands for standard functional toolkit.

Comparison notes

Operator counterparts aren't and can't be fully equivalent.
"Kinda the same" – is the current definition.

The following projects, were created with different goals and tradeoffs in mind, so every comparison and analogy is subjective and can be argued. The presence of some operator is not necessary good, as well as the abscence is not necessary bad.

Note, that primitives differ for each library. In descriptions, we broadly refer to all the "observable primitives" as streams*, though, technically speaking, some of them are rather stream-like entities.

To find something, search for a term you know.

API

Create

Create an empty stream

Create a stream from a single value

Create a stream from an array

Create a stream from a promise

Create a stream from an event

Create a stream from a callback

Prepend a stream with a value

  • KefirJS: merge + constant
  • MostJS: startWith
  • RxJS: startWith
  • XStream: startWith

Transform (data events)

Map value one-to-one

  • KefirJS: map
  • MostJS: map, constant
  • RxJS: map, mapTo
  • XStream: map

Filter value by a predicate

  • KefirJS: filter
  • MostJS: filter
  • RxJS: filter
  • XStream: filter

Skip N initial values

  • KefirJS: skip
  • MostJS: skip
  • RxJS: skip
  • XStream: drop

Take N initial values

  • KefirJS: take
  • MostJS: take
  • RxJS: take
  • XStream: take

Make a value from an accumulator and a next value

  • KefirJS: scan
  • MostJS: scan
  • RxJS: scan
  • XStream: fold

Combine

Merge multiple streams together

  • KefirJS: merge
  • MostJS: merge
  • RxJS: merge
  • XStream: merge

Pay attention that Kefir's merge accepts arrays while others are variadic.

Combine multiple streams together

  • KefirJS: combine
  • MostJS: combine
  • RxJS: combineLatest
  • XStream: combine

Sample a stream by another stream

  • KefirJS: combine, sampledBy
  • MostJS: sample, sampleWith
  • RxJS: sample, withLatestFrom
  • XStream: sampleCombine

Chain streams sequentially

  • KefirJS: flatMapConcat
  • MostJS: concatMap
  • RxJS: concatMap
  • XStream: map + flattenSequentially

Create

Create stream from non-stream values.

KefirJS MostJS RxJS XStream
interval periodic interval + map periodic
repeat of + R.range repeat of + R.range
? iterate generate ?
? generate generate ?

Mapper

Modify events one to one.

KefirJS MostJS RxJS XStream
delay delay delay combine(delay(500))
– (map) timestamp timestamp – (map)

Transforms

Modify events * to *.

MostJS RxJS XStream
chain / flatMap flatMap map + flattenConcurrently
map + switch switchMap / flatMapLatest map + flatten
join mergeAll flatten
loop scan + map fold + map
– (custom) bufferWithCount ?

Filters

Skip events by predicate or signal.

MostJS RxJS XStream
skipRepeats distinctUntilChanged dropRepeats
skipRepeatsWith – (scan) dropRepeats
slice skip + take drop + take
skipWhile skipWhile fold + filter + map
takeWhile takeWhile filter + endWhen
since / skipUntil skipUntil fold + filter + map
until / takeUntil takeUntil filter + endWhen
during window + take(1) ?

Combinators

Combine multiple streams into single.

MostJS RxJS XStream
zip zip ?
concat concat concat
ap combineLatest ?

Side effects

Produce side effect for every event.

MostJS RxJS XStream
tap do / tap debug

Ending

Operators which target end event somehow.

MostJS RxJS XStream
empty empty empty
never never never
continueWith ? concat

Concurrency

MostJS RxJS
– (custom) amb / race

History

MostJS RxJS
– (custom)

Design diffs

RxJS

  1. Three primitives: Observer, Observable, Subject.
  2. Observables end on error.
  3. Provides API to handle errors.
  4. Does not provide API to handle ending.

KefirJS

  1. Two primitives: Stream and Property (like XStream).
  2. Observables does not end on error (by default).
  3. Provides API to handle errors.
  4. Provides API to handle ending.

MostJS

  1. One primitive: Stream (+ community-driven).
  2. Separate packages for subject-like and property-like primitives.
  3. Provides API to handle errors.
  4. Provides API to handle ending.

XStream

  1. Two primitives: Stream and MemoryStream (like KefirJS).
  2. Always multicast. A Stream is like an RxJS Subject.
  3. Streams end on error.

Common

RxJS does not emit initial scan value as event (use startWith for that).

Rx.Observable.interval(100).map(x => 1)
  .scan(add, 0);
  .subscribe(console.log); // 1--2--3--...

Most.periodic(100, 1)
  .scan(add, 0);
  .observe(console.log); // 0--1--2--3--...

Found docs / API quirks

MostJS

startWith vs sampleWith vs continueWith + recoverWith vs skipRepeatsWith
(val vs none vs func vs stream)

tap is listed in "Transform" section.

RxJS

startWith is listed in "Combine" section.

mergeAll is listed in "Combine" section.

distinct is not listed in "Filtering" section.

takeUntil is not listed in "Filtering" section.

just / return should be deprecated in favor of of.

fromArray should be deprecated in favor of from.

bacon-vs-kefir – BaconJS vs KefirJS API comparison

dataflows – web arch. dataflow comparison

stream-conversions – tool for cross-library stream conversions

Additional Read

https://github.com/cujojs/most/issues/171

https://twitter.com/rpominov/status/689566111734599683

https://github.com/zenparsing/es-observable/issues/66

Open Source Agenda is not affiliated with "Reactive Polyglot" Project. README Source: ivan-kleshnin/reactive-polyglot
Stars
69
Open Issues
2
Last Commit
5 years ago

Open Source Agenda Badge

Open Source Agenda Rating