{"id":17371895,"url":"https://github.com/ivan-kleshnin/reactive-polyglot","last_synced_at":"2025-04-15T02:37:04.328Z","repository":{"id":41583783,"uuid":"50342853","full_name":"ivan-kleshnin/reactive-polyglot","owner":"ivan-kleshnin","description":"FRP libraries / langs compared","archived":false,"fork":false,"pushed_at":"2019-03-15T05:57:14.000Z","size":40,"stargazers_count":70,"open_issues_count":2,"forks_count":5,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-28T15:05:28.448Z","etag":null,"topics":["baconjs","comparison","frp","kefir","mostjs","reactive","reactivity","rxjs","xstream"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ivan-kleshnin.png","metadata":{"files":{"readme":"README.md","changelog":"history.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-01-25T10:18:58.000Z","updated_at":"2024-05-07T09:46:00.000Z","dependencies_parsed_at":"2022-09-16T17:00:33.004Z","dependency_job_id":null,"html_url":"https://github.com/ivan-kleshnin/reactive-polyglot","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivan-kleshnin%2Freactive-polyglot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivan-kleshnin%2Freactive-polyglot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivan-kleshnin%2Freactive-polyglot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivan-kleshnin%2Freactive-polyglot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ivan-kleshnin","download_url":"https://codeload.github.com/ivan-kleshnin/reactive-polyglot/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248995102,"owners_count":21195497,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["baconjs","comparison","frp","kefir","mostjs","reactive","reactivity","rxjs","xstream"],"created_at":"2024-10-16T01:06:09.207Z","updated_at":"2025-04-15T02:37:04.084Z","avatar_url":"https://github.com/ivan-kleshnin.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Reactive polyglot\n\n**`R.`** [(Ramda)](http://ramdajs.com/0.19.1/index.html) stands for standard functional toolkit.\n\n### Comparison notes\n\nOperator counterparts aren't and can't be fully equivalent.\u003cbr/\u003e\n\"Kinda the same\" – is the current definition.\n\nThe following projects, were created with different goals and tradeoffs in mind, so every comparison\nand analogy is subjective and can be argued. The presence of some operator is not necessary good, as\nwell as the abscence is not necessary bad.\n\nNote, that primitives differ for each library. In descriptions, we broadly refer to all the \"observable\nprimitives\" as **streams***, though, technically speaking, some of them are rather stream-like entities.\n\nTo find something, search for a term you know.\n\n## API\n\n### Create\n\n#### Create an empty stream\n\n* KefirJS: [`never`](http://kefirjs.github.io/kefir/#never)\n* MostJS: [`empty`](https://github.com/cujojs/most/blob/master/docs/api.md#mostempty)\n* RxJS: [`of`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/of.md)\n* XStream: [`empty`](https://github.com/staltz/xstream#of)\n\n#### Create a stream from a single value\n\n* KefirJS: [`constant`](http://kefirjs.github.io/kefir/#constant)\n* MostJS: [`of`](https://github.com/cujojs/most/blob/master/docs/api.md#mostjust), [`just`](https://github.com/cujojs/most/blob/master/docs/api.md#mostjust)\n* RxJS: [`of`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/of.md), [`just`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/return.md)\n* XStream: [`of`](https://github.com/staltz/xstream#of)\n\n#### Create a stream from an array\n\n* KefirJS: [`sequentially`](http://kefirjs.github.io/kefir/#sequentially)\n* MostJS: [`from`](https://github.com/cujojs/most/blob/master/docs/api.md#mostfrom)\n* RxJS: [`from`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/from.md), [`of`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/of.md)\n* XStream: [`from`](https://github.com/staltz/xstream#from), [`fromArray`](https://github.com/staltz/xstream#fromArray)\n\n#### Create a stream from a promise\n\n* KefirJS: [`fromPromise`](http://kefirjs.github.io/kefir/#from-promise)\n* MostJS: [`fromPromise`](https://github.com/cujojs/most/blob/master/docs/api.md#mostfrompromise)\n* RxJS: [`fromPromise`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/frompromise.md)\n* XStream: [`fromPromise`](https://github.com/staltz/xstream#fromPromise)\n\n#### Create a stream from an event\n\n* KefirJS: [`fromEvents`](http://kefirjs.github.io/kefir/#from-event)\n* MostJS: [`fromEvent`](https://github.com/cujojs/most/blob/master/docs/api.md#mostfromevent)\n* RxJS: [`fromEvent`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/fromevent.md)\n* XStream: [`fromEvent`](https://github.com/staltz/xstream/blob/master/EXTRA_DOCS.md#fromEvent)\n\n#### Create a stream from a callback\n\n* KefirJS: [`stream`](http://kefirjs.github.io/kefir/#stream), [`fromCallback`](http://kefirjs.github.io/kefir/#from-callback), [`fromNodeCallback`](http://kefirjs.github.io/kefir/#from-node-callback), [`fromPoll`](http://kefirjs.github.io/kefir/#from-poll)\n* MostJS: `new Stream`\n* RxJS: `new Observable`, `bindCallback`, `bindNodeCallback`\n* XStream: `? (make a promise first)`\n\n#### Prepend a stream with a value\n\n* KefirJS: [`merge`](http://kefirjs.github.io/kefir/#merge) `+` [`constant`](http://kefirjs.github.io/kefir/#constant)\n* MostJS: `startWith`\n* RxJS: [`startWith`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/startwith.md)\n* XStream: `startWith`\n\n### Transform (data events)\n\n#### Map value one-to-one\n\n* KefirJS: [`map`](http://kefirjs.github.io/kefir/#map)\n* MostJS: `map`, `constant`\n* RxJS: [`map`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/select.md), `mapTo`\n* XStream: `map`\n\n#### Filter value by a predicate\n\n* KefirJS: [`filter`](http://kefirjs.github.io/kefir/#filter)\n* MostJS: `filter`\n* RxJS: [`filter`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/where.md)\n* XStream: `filter`\n\n#### Skip N initial values\n\n* KefirJS: [`skip`](http://kefirjs.github.io/kefir/#skip)\n* MostJS: `skip`\n* RxJS: [`skip`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/skip.md)\n* XStream: `drop`\n\n#### Take N initial values\n\n* KefirJS: [`take`](http://kefirjs.github.io/kefir/#take)\n* MostJS: `take`\n* RxJS: [`take`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/take.md)\n* XStream: `take`\n\n#### Make a value from an accumulator and a next value\n\n* KefirJS: [`scan`](http://kefirjs.github.io/kefir/#scan)\n* MostJS: `scan`\n* RxJS: [`scan`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/scan.md)\n* XStream: `fold`\n\n### Combine\n\n#### Merge multiple streams together\n\n* KefirJS: [`merge`](http://kefirjs.github.io/kefir/#merge)\n* MostJS: `merge`\n* RxJS: [`merge`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/merge.md)\n* XStream: `merge`\n\nPay attention that Kefir's `merge` accepts arrays while others are variadic.\n\n#### Combine multiple streams together\n\n* KefirJS: [`combine`](http://kefirjs.github.io/kefir/#combine)\n* MostJS: `combine`\n* RxJS: [`combineLatest`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/combinelatest.md)\n* XStream: `combine`\n\n#### Sample a stream by another stream\n\n* KefirJS: [`combine`](http://kefirjs.github.io/kefir/#combine), [`sampledBy`](http://kefirjs.github.io/kefir/#obs-sampled-by)\n* MostJS: `sample`, `sampleWith`\n* RxJS: [`sample`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/sample.md), [`withLatestFrom`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/withlatestfrom.md)\n* XStream: `sampleCombine`\n\n#### Chain streams sequentially\n\n* KefirJS: [`flatMapConcat`](http://kefirjs.github.io/kefir/#flat-map-concat)\n* MostJS: [`concatMap`](https://github.com/cujojs/most/blob/master/docs/api.md#concatmap)\n* RxJS: [`concatMap`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/concatmap.md)\n* XStream: `map + flattenSequentially`\n\n---\n\n### Create\n\nCreate stream from non-stream values.\n\n\u003ctable\u003e\n\u003ctr\u003e\n  \u003cth\u003eKefirJS\u003c/th\u003e\n  \u003cth\u003eMostJS\u003c/th\u003e\n  \u003cth\u003eRxJS\u003c/th\u003e\n  \u003cth\u003eXStream\u003c/th\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003einterval\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003eperiodic\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003einterval + map\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003eperiodic\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003erepeat\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003eof + R.range\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003erepeat\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003eof + R.range\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003e?\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003eiterate\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003egenerate\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e?\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003e?\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003egenerate\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003egenerate\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e?\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n### Mapper\n\nModify events one to one.\n\n\u003ctable\u003e\n\u003ctr\u003e\n  \u003cth\u003eKefirJS\u003c/th\u003e\n  \u003cth\u003eMostJS\u003c/th\u003e\n  \u003cth\u003eRxJS\u003c/th\u003e\n  \u003cth\u003eXStream\u003c/th\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003edelay\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003edelay\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003edelay\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003ecombine(delay(500))\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003e– (map)\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003etimestamp\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003etimestamp\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003e– (map)\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n### Transforms\n\nModify events * to *.\n\n\u003ctable\u003e\n\u003ctr\u003e\n  \u003cth\u003eMostJS\u003c/th\u003e\n  \u003cth\u003eRxJS\u003c/th\u003e\n  \u003cth\u003eXStream\u003c/th\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003echain / flatMap\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003eflatMap\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003emap + flattenConcurrently\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003emap + switch\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003eswitchMap / flatMapLatest\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003emap + flatten\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003ejoin\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003emergeAll\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003eflatten\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003eloop\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003escan + map\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003efold + map\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003e– (\u003ca href=\"bufferWithCount.md\"\u003ecustom\u003c/a\u003e)\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003ebufferWithCount\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e?\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n### Filters\n\nSkip events by predicate or signal.\n\n\u003ctable\u003e\n\u003ctr\u003e\n  \u003cth\u003eMostJS\u003c/th\u003e\n  \u003cth\u003eRxJS\u003c/th\u003e\n  \u003cth\u003eXStream\u003c/th\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003eskipRepeats\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003edistinctUntilChanged\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003edropRepeats\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003eskipRepeatsWith\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003e– (scan)\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003edropRepeats\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003eslice\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003eskip + take\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003edrop + take\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003eskipWhile\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003eskipWhile\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003efold + filter + map\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003etakeWhile\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003etakeWhile\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003efilter + endWhen\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003esince / skipUntil\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003eskipUntil\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003efold + filter + map\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003euntil / takeUntil\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003etakeUntil\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003efilter + endWhen\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003eduring\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003ewindow + take(1)\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e?\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n### Combinators\n\nCombine multiple streams into single.\n\n\u003ctable\u003e\n\u003ctr\u003e\n  \u003cth\u003eMostJS\u003c/th\u003e\n  \u003cth\u003eRxJS\u003c/th\u003e\n  \u003cth\u003eXStream\u003c/th\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003ezip\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003ezip\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e?\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003econcat\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003econcat\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003econcat\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003eap\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003ecombineLatest\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e?\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n### Side effects\n\nProduce side effect for every event.\n\n\u003ctable\u003e\n\u003ctr\u003e\n  \u003cth\u003eMostJS\u003c/th\u003e\n  \u003cth\u003eRxJS\u003c/th\u003e\n  \u003cth\u003eXStream\u003c/th\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003etap\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003edo / tap\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003edebug\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n### Ending\n\nOperators which target **end** event somehow.\n\n\u003ctable\u003e\n\u003ctr\u003e\n  \u003cth\u003eMostJS\u003c/th\u003e\n  \u003cth\u003eRxJS\u003c/th\u003e\n  \u003cth\u003eXStream\u003c/th\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003eempty\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003eempty\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003eempty\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003enever\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003enever\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003enever\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003econtinueWith\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003e?\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003econcat\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n### Concurrency\n\n\u003ctable\u003e\n\u003ctr\u003e\n  \u003cth\u003eMostJS\u003c/th\u003e\n  \u003cth\u003eRxJS\u003c/th\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003e– (\u003ca href=\"https://github.com/ivan-kleshnin/reactive-polyglot/wiki/race\"\u003ecustom\u003c/a\u003e)\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003eamb / race\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n### History\n\n\u003ctable\u003e\n\u003ctr\u003e\n  \u003cth\u003eMostJS\u003c/th\u003e\n  \u003cth\u003eRxJS\u003c/th\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd colspan=\"2\"\u003e\u003ccode\u003e– (\u003ca href=\"history.md\"\u003ecustom\u003c/a\u003e)\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n### Design diffs\n\n#### RxJS\n\n1. Three primitives: `Observer`, `Observable`, `Subject`.\n2. Observables end on error.\n3. Provides API to handle errors.\n3. Does not provide API to handle ending.\n\n#### KefirJS\n\n1. Two primitives: `Stream` and `Property` (like XStream).\n2. Observables does not end on error (by default).\n3. Provides API to handle errors.\n4. Provides API to handle ending.\n\n#### MostJS\n\n1. One primitive: `Stream` (+ community-driven).\n2. Separate packages for [subject-like](https://github.com/TylorS/most-subject) and [property-like](https://github.com/mostjs/hold) primitives.\n3. Provides API to handle errors.\n4. Provides API to handle ending.\n\n#### XStream\n\n1. Two primitives: `Stream` and `MemoryStream` (like KefirJS).\n2. Always multicast. A Stream is like an RxJS Subject.\n3. Streams end on error.\n\n#### Common\n\nRxJS does not emit initial `scan` value as event (use `startWith` for that).\n\n```js\nRx.Observable.interval(100).map(x =\u003e 1)\n  .scan(add, 0);\n  .subscribe(console.log); // 1--2--3--...\n\nMost.periodic(100, 1)\n  .scan(add, 0);\n  .observe(console.log); // 0--1--2--3--...\n```\n\n### Found docs / API quirks\n\n#### MostJS\n\n`startWith` vs `sampleWith` vs `continueWith` + `recoverWith` vs `skipRepeatsWith`\u003cbr/\u003e\n(val vs none vs func vs stream)\n\n`tap` is listed in \"Transform\" section.\n\n#### RxJS\n\n`startWith` is listed in \"Combine\" section.\n\n`mergeAll` is listed in \"Combine\" section.\n\n`distinct` is not listed in \"Filtering\" section.\n\n`takeUntil` is not listed in \"Filtering\" section.\n\n`just` / `return` should be deprecated in favor of `of`.\n\n`fromArray` should be deprecated in favor of `from`.\n\n### Links\n\n[bacon-vs-kefir](https://github.com/rpominov/kefir/blob/master/bacon-vs-kefir-api.md) – BaconJS vs KefirJS API comparison\n\n[dataflows](https://github.com/ivan-kleshnin/dataflows) – web arch. dataflow comparison\n\n[stream-conversions](https://github.com/TylorS/stream-conversions) – tool for cross-library stream conversions\n\n### Additional Read\n\nhttps://github.com/cujojs/most/issues/171\n\nhttps://twitter.com/rpominov/status/689566111734599683\n\nhttps://github.com/zenparsing/es-observable/issues/66\n\n# Reactive polyglot\n\n**`R.`** [(Ramda)](http://ramdajs.com/0.19.1/index.html) stands for standard functional toolkit.\n\n### Comparison notes\n\nOperator counterparts aren't and can't be fully equivalent.\u003cbr/\u003e\n\"Kinda the same\" – is the current definition.\n\nThe following projects, were created with different goals and tradeoffs in mind, so every comparison\nand analogy is subjective and can be argued. The presence of some operator is not necessary good, as\nwell as the abscence is not necessary bad.\n\nNote, that primitives differ for each library. In descriptions, we broadly refer to all the \"observable\nprimitives\" as **streams***, though, technically speaking, some of them are rather stream-like entities.\n\nTo find something, search for a term you know.\n\n## API\n\n### Create\n\n#### Create an empty stream\n\n* KefirJS: [`never`](http://kefirjs.github.io/kefir/#never)\n* MostJS: [`empty`](https://github.com/cujojs/most/blob/master/docs/api.md#mostempty)\n* RxJS: [`of`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/of.md)\n* XStream: [`empty`](https://github.com/staltz/xstream#of)\n\n#### Create a stream from a single value\n\n* KefirJS: [`constant`](http://kefirjs.github.io/kefir/#constant)\n* MostJS: [`of`](https://github.com/cujojs/most/blob/master/docs/api.md#mostjust), [`just`](https://github.com/cujojs/most/blob/master/docs/api.md#mostjust)\n* RxJS: [`of`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/of.md), [`just`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/return.md)\n* XStream: [`of`](https://github.com/staltz/xstream#of)\n\n#### Create a stream from an array\n\n* KefirJS: [`sequentially`](http://kefirjs.github.io/kefir/#sequentially)\n* MostJS: [`from`](https://github.com/cujojs/most/blob/master/docs/api.md#mostfrom)\n* RxJS: [`from`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/from.md), [`of`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/of.md)\n* XStream: [`from`](https://github.com/staltz/xstream#from), [`fromArray`](https://github.com/staltz/xstream#fromArray)\n\n#### Create a stream from a promise\n\n* KefirJS: [`fromPromise`](http://kefirjs.github.io/kefir/#from-promise)\n* MostJS: [`fromPromise`](https://github.com/cujojs/most/blob/master/docs/api.md#mostfrompromise)\n* RxJS: [`fromPromise`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/frompromise.md)\n* XStream: [`fromPromise`](https://github.com/staltz/xstream#fromPromise)\n\n#### Create a stream from an event\n\n* KefirJS: [`fromEvents`](http://kefirjs.github.io/kefir/#from-event)\n* MostJS: [`fromEvent`](https://github.com/cujojs/most/blob/master/docs/api.md#mostfromevent)\n* RxJS: [`fromEvent`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/fromevent.md)\n* XStream: [`fromEvent`](https://github.com/staltz/xstream/blob/master/EXTRA_DOCS.md#fromEvent)\n\n#### Create a stream from a callback\n\n* KefirJS: [`stream`](http://kefirjs.github.io/kefir/#stream), [`fromCallback`](http://kefirjs.github.io/kefir/#from-callback), [`fromNodeCallback`](http://kefirjs.github.io/kefir/#from-node-callback), [`fromPoll`](http://kefirjs.github.io/kefir/#from-poll)\n* MostJS: `new Stream`\n* RxJS: `new Observable`, `bindCallback`, `bindNodeCallback`\n* XStream: `? (make a promise first)`\n\n#### Prepend a stream with a value\n\n* KefirJS: [`merge`](http://kefirjs.github.io/kefir/#merge) `+` [`constant`](http://kefirjs.github.io/kefir/#constant)\n* MostJS: `startWith`\n* RxJS: `startWith`\n* XStream: `startWith`\n\n### Transform (data events)\n\n#### Map value one-to-one\n\n* KefirJS: [`map`](http://kefirjs.github.io/kefir/#map)\n* MostJS: `map`, `constant`\n* RxJS: `map`, `mapTo`\n* XStream: `map`\n\n#### Filter value by a predicate\n\n* KefirJS: [`filter`](http://kefirjs.github.io/kefir/#filter)\n* MostJS: `filter`\n* RxJS: `filter`\n* XStream: `filter`\n\n#### Skip N initial values\n\n* KefirJS: [`skip`](http://kefirjs.github.io/kefir/#skip)\n* MostJS: `skip`\n* RxJS: `skip`\n* XStream: `drop`\n\n#### Take N initial values\n\n* KefirJS: [`take`](http://kefirjs.github.io/kefir/#take)\n* MostJS: `take`\n* RxJS: `take`\n* XStream: `take`\n\n#### Make a value from an accumulator and a next value\n\n* KefirJS: [`scan`](http://kefirjs.github.io/kefir/#scan)\n* MostJS: `scan`\n* RxJS: `scan`\n* XStream: `fold`\n\n### Combine\n\n#### Merge multiple streams together\n\n* KefirJS: [`merge`](http://kefirjs.github.io/kefir/#merge)\n* MostJS: `merge`\n* RxJS: `merge`\n* XStream: `merge`\n\nPay attention that Kefir's `merge` accepts arrays while others are variadic.\n\n#### Combine multiple streams together\n\n* KefirJS: [`combine`](http://kefirjs.github.io/kefir/#combine)\n* MostJS: `combine`\n* RxJS: `combineLatest`\n* XStream: `combine`\n\n#### Sample a stream by another stream\n\n* KefirJS: [`combine`](http://kefirjs.github.io/kefir/#combine), [`sampledBy`](http://kefirjs.github.io/kefir/#obs-sampled-by)\n* MostJS: `sample`, `sampleWith`\n* RxJS: `sample`, `withLatestFrom`\n* XStream: `sampleCombine`\n\n#### Chain streams sequentially\n\n* KefirJS: [`flatMapConcat`](http://kefirjs.github.io/kefir/#flat-map-concat)\n* MostJS: `concatMap`\n* RxJS: `concatMap`\n* XStream: `map + flattenSequentially`\n\n---\n\n### Create\n\nCreate stream from non-stream values.\n\n\u003ctable\u003e\n\u003ctr\u003e\n  \u003cth\u003eKefirJS\u003c/th\u003e\n  \u003cth\u003eMostJS\u003c/th\u003e\n  \u003cth\u003eRxJS\u003c/th\u003e\n  \u003cth\u003eXStream\u003c/th\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003einterval\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003eperiodic\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003einterval + map\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003eperiodic\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003erepeat\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003eof + R.range\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003erepeat\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003eof + R.range\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003e?\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003eiterate\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003egenerate\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e?\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003e?\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003egenerate\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003egenerate\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e?\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n### Mapper\n\nModify events one to one.\n\n\u003ctable\u003e\n\u003ctr\u003e\n  \u003cth\u003eKefirJS\u003c/th\u003e\n  \u003cth\u003eMostJS\u003c/th\u003e\n  \u003cth\u003eRxJS\u003c/th\u003e\n  \u003cth\u003eXStream\u003c/th\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003edelay\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003edelay\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003edelay\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003ecombine(delay(500))\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003e– (map)\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003etimestamp\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003etimestamp\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003e– (map)\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n### Transforms\n\nModify events * to *.\n\n\u003ctable\u003e\n\u003ctr\u003e\n  \u003cth\u003eMostJS\u003c/th\u003e\n  \u003cth\u003eRxJS\u003c/th\u003e\n  \u003cth\u003eXStream\u003c/th\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003echain / flatMap\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003eflatMap\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003emap + flattenConcurrently\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003emap + switch\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003eswitchMap / flatMapLatest\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003emap + flatten\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003ejoin\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003emergeAll\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003eflatten\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003eloop\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003escan + map\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003efold + map\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003e– (\u003ca href=\"bufferWithCount.md\"\u003ecustom\u003c/a\u003e)\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003ebufferWithCount\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e?\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n### Filters\n\nSkip events by predicate or signal.\n\n\u003ctable\u003e\n\u003ctr\u003e\n  \u003cth\u003eMostJS\u003c/th\u003e\n  \u003cth\u003eRxJS\u003c/th\u003e\n  \u003cth\u003eXStream\u003c/th\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003eskipRepeats\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003edistinctUntilChanged\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003edropRepeats\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003eskipRepeatsWith\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003e– (scan)\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003edropRepeats\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003eslice\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003eskip + take\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003edrop + take\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003eskipWhile\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003eskipWhile\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003efold + filter + map\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003etakeWhile\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003etakeWhile\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003efilter + endWhen\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003esince / skipUntil\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003eskipUntil\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003efold + filter + map\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003euntil / takeUntil\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003etakeUntil\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003efilter + endWhen\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003eduring\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003ewindow + take(1)\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e?\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n### Combinators\n\nCombine multiple streams into single.\n\n\u003ctable\u003e\n\u003ctr\u003e\n  \u003cth\u003eMostJS\u003c/th\u003e\n  \u003cth\u003eRxJS\u003c/th\u003e\n  \u003cth\u003eXStream\u003c/th\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003ezip\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003ezip\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e?\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003econcat\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003econcat\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003econcat\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003eap\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003ecombineLatest\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e?\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n### Side effects\n\nProduce side effect for every event.\n\n\u003ctable\u003e\n\u003ctr\u003e\n  \u003cth\u003eMostJS\u003c/th\u003e\n  \u003cth\u003eRxJS\u003c/th\u003e\n  \u003cth\u003eXStream\u003c/th\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003etap\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003edo / tap\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003edebug\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n### Ending\n\nOperators which target **end** event somehow.\n\n\u003ctable\u003e\n\u003ctr\u003e\n  \u003cth\u003eMostJS\u003c/th\u003e\n  \u003cth\u003eRxJS\u003c/th\u003e\n  \u003cth\u003eXStream\u003c/th\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003eempty\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003eempty\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003eempty\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003enever\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003enever\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003enever\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003econtinueWith\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003e?\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003econcat\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n### Concurrency\n\n\u003ctable\u003e\n\u003ctr\u003e\n  \u003cth\u003eMostJS\u003c/th\u003e\n  \u003cth\u003eRxJS\u003c/th\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003e\u003ccode\u003e– (\u003ca href=\"https://github.com/ivan-kleshnin/reactive-polyglot/wiki/race\"\u003ecustom\u003c/a\u003e)\u003c/code\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003ccode\u003eamb / race\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n### History\n\n\u003ctable\u003e\n\u003ctr\u003e\n  \u003cth\u003eMostJS\u003c/th\u003e\n  \u003cth\u003eRxJS\u003c/th\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd colspan=\"2\"\u003e\u003ccode\u003e– (\u003ca href=\"history.md\"\u003ecustom\u003c/a\u003e)\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n### Design diffs\n\n#### RxJS\n\n1. Three primitives: `Observer`, `Observable`, `Subject`.\n2. Observables end on error.\n3. Provides API to handle errors.\n3. Does not provide API to handle ending.\n\n#### KefirJS\n\n1. Two primitives: `Stream` and `Property` (like XStream).\n2. Observables does not end on error (by default).\n3. Provides API to handle errors.\n4. Provides API to handle ending.\n\n#### MostJS\n\n1. One primitive: `Stream` (+ community-driven).\n2. Separate packages for [subject-like](https://github.com/TylorS/most-subject) and [property-like](https://github.com/mostjs/hold) primitives.\n3. Provides API to handle errors.\n4. Provides API to handle ending.\n\n#### XStream\n\n1. Two primitives: `Stream` and `MemoryStream` (like KefirJS).\n2. Always multicast. A Stream is like an RxJS Subject.\n3. Streams end on error.\n\n#### Common\n\nRxJS does not emit initial `scan` value as event (use `startWith` for that).\n\n```js\nRx.Observable.interval(100).map(x =\u003e 1)\n  .scan(add, 0);\n  .subscribe(console.log); // 1--2--3--...\n\nMost.periodic(100, 1)\n  .scan(add, 0);\n  .observe(console.log); // 0--1--2--3--...\n```\n\n### Found docs / API quirks\n\n#### MostJS\n\n`startWith` vs `sampleWith` vs `continueWith` + `recoverWith` vs `skipRepeatsWith`\u003cbr/\u003e\n(val vs none vs func vs stream)\n\n`tap` is listed in \"Transform\" section.\n\n#### RxJS\n\n`startWith` is listed in \"Combine\" section.\n\n`mergeAll` is listed in \"Combine\" section.\n\n`distinct` is not listed in \"Filtering\" section.\n\n`takeUntil` is not listed in \"Filtering\" section.\n\n`just` / `return` should be deprecated in favor of `of`.\n\n`fromArray` should be deprecated in favor of `from`.\n\n### Links\n\n[bacon-vs-kefir](https://github.com/rpominov/kefir/blob/master/bacon-vs-kefir-api.md) – BaconJS vs KefirJS API comparison\n\n[dataflows](https://github.com/ivan-kleshnin/dataflows) – web arch. dataflow comparison\n\n[stream-conversions](https://github.com/TylorS/stream-conversions) – tool for cross-library stream conversions\n\n### Additional Read\n\nhttps://github.com/cujojs/most/issues/171\n\nhttps://twitter.com/rpominov/status/689566111734599683\n\nhttps://github.com/zenparsing/es-observable/issues/66\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fivan-kleshnin%2Freactive-polyglot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fivan-kleshnin%2Freactive-polyglot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fivan-kleshnin%2Freactive-polyglot/lists"}