{"action":"created","issue":{"url":"https://api.github.com/repos/ubolonton/js-csp/issues/40","repository_url":"https://api.github.com/repos/ubolonton/js-csp","labels_url":"https://api.github.com/repos/ubolonton/js-csp/issues/40/labels{/name}","comments_url":"https://api.github.com/repos/ubolonton/js-csp/issues/40/comments","events_url":"https://api.github.com/repos/ubolonton/js-csp/issues/40/events","html_url":"https://github.com/ubolonton/js-csp/issues/40","id":56958732,"number":40,"title":"js-CSP compared with streams and events","user":{"login":"nmn","id":3582514,"avatar_url":"https://avatars.githubusercontent.com/u/3582514?v=3","gravatar_id":"","url":"https://api.github.com/users/nmn","html_url":"https://github.com/nmn","followers_url":"https://api.github.com/users/nmn/followers","following_url":"https://api.github.com/users/nmn/following{/other_user}","gists_url":"https://api.github.com/users/nmn/gists{/gist_id}","starred_url":"https://api.github.com/users/nmn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nmn/subscriptions","organizations_url":"https://api.github.com/users/nmn/orgs","repos_url":"https://api.github.com/users/nmn/repos","events_url":"https://api.github.com/users/nmn/events{/privacy}","received_events_url":"https://api.github.com/users/nmn/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":22,"created_at":"2015-02-08T17:09:06Z","updated_at":"2016-02-02T21:02:20Z","closed_at":null,"body":"@jlongster wrote a great article introducing js-CSP, and does a short comparison with promises. I think a more fair comparison would be to streams such as RxJS and Bacon.js.\r\n\r\nThis, issue will also play into **Multiplexing, mixing, publishing/subscribing** .\r\n\r\nThe major difference I see between channels and streams other than generator functions and API is:\r\n\r\n## One-To-Many Streams\r\nStreams act like events and broadcast their values. As a result you can attach many listeners to the same stream of data. Channels, act as value bridges. One value put on one end, is only received by one receiver.\r\n\r\n```\r\n// stream is a stream of data.\r\nvar s1 = stream.map(fn1);\r\nvar s2 = stream.map(fn2);\r\n\r\n// both s1, and s2, will be mapped from all the values fed into stream.\r\n// The values are copied for every method called on stream.\r\n```\r\n\r\nHowever, the one-to-many data stream can be simulated with a helper function, and Dropping channels.\r\n```\r\nfunction toMany(ch){\r\n  var channels = [];\r\n  go(function*(){\r\n    while(true){\r\n      var val = yield take(ch);\r\n      for(var i = 0; i < channels.length; i++){\r\n        yield put(channels[i], val);\r\n      }\r\n    }\r\n  });\r\n\r\n  return function(){\r\n    var ch = chan(buffers.dropping(0));\r\n    channels.push(ch);\r\n    return ch;\r\n  }\r\n}\r\n```\r\n\r\nNow, this can be used in exactly the same way that streams from RxJS and Bacon can be used.\r\n*(it would be better to use a set to hold channels rather than an array in an ES6 world)*\r\n\r\n```\r\n// ch is a channel where values are being put\r\nvar subscribe = toMany(ch);\r\nvar ch1 = subscribe();\r\nvar ch2 = subscribe();\r\n// ch1 and ch2 now both have all the values being put onto ch.\r\n// using methods from transducers, and toMany downstream again, you can simulate all the behaviour of streams.\r\n```\r\n\r\nThis, I think shows the power and flexibility of channels. RxJS and BaconJS are amazing for doing async programming in a pre-generator world. But Channels are a lower-level construct that can be used to be used in the same ways, but also in other ways.\r\n\r\nWith a few helper methods, channels can be used to achieve the same semantics of promises or of streams, or a one receiver semantic that is unique.\r\n\r\n**Note**: this function like other functions, still needs work to account for closed channels.\r\n\r\nOne downside of the one-to-many semantic of streams is that it is hard to send a message upstream telling the origin to stop emitting data."},"comment":{"url":"https://api.github.com/repos/ubolonton/js-csp/issues/comments/178816967","html_url":"https://github.com/ubolonton/js-csp/issues/40#issuecomment-178816967","issue_url":"https://api.github.com/repos/ubolonton/js-csp/issues/40","id":178816967,"user":{"login":"ivan-kleshnin","id":2128182,"avatar_url":"https://avatars.githubusercontent.com/u/2128182?v=3","gravatar_id":"","url":"https://api.github.com/users/ivan-kleshnin","html_url":"https://github.com/ivan-kleshnin","followers_url":"https://api.github.com/users/ivan-kleshnin/followers","following_url":"https://api.github.com/users/ivan-kleshnin/following{/other_user}","gists_url":"https://api.github.com/users/ivan-kleshnin/gists{/gist_id}","starred_url":"https://api.github.com/users/ivan-kleshnin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ivan-kleshnin/subscriptions","organizations_url":"https://api.github.com/users/ivan-kleshnin/orgs","repos_url":"https://api.github.com/users/ivan-kleshnin/repos","events_url":"https://api.github.com/users/ivan-kleshnin/events{/privacy}","received_events_url":"https://api.github.com/users/ivan-kleshnin/received_events","type":"User","site_admin":false},"created_at":"2016-02-02T21:02:20Z","updated_at":"2016-02-02T21:02:20Z","body":"@lucasmreis, yeah, thanks for pushing me into right direction. I tried to grok Elm but as API was constantly changed, most examples were broken and I kinda abandoned it then.\r\n\r\nMaybe @danyx23 will answer us. For example, I'm curious how to implement \"waves\" of values in Elm having no nested signals. It's crucial for many animations.\r\n\r\n```js\r\nimport {Observable} from \"rx\";\r\n\r\nlet s = Observable.interval(1000).flatMap(\r\n  Observable.for(\r\n    [0, 1, 2, 3, 4], (v) => Observable.of(v).delay(v * 50)\r\n  )\r\n);\r\n\r\ns.subscribe(console.log);\r\n\r\n// 0-1-2-3-4-----0-1-2-3-4-----....\r\n```"}}