{"action":"created","issue":{"url":"https://api.github.com/repos/ReactiveX/RxJS/issues/60","repository_url":"https://api.github.com/repos/ReactiveX/RxJS","labels_url":"https://api.github.com/repos/ReactiveX/RxJS/issues/60/labels{/name}","comments_url":"https://api.github.com/repos/ReactiveX/RxJS/issues/60/comments","events_url":"https://api.github.com/repos/ReactiveX/RxJS/issues/60/events","html_url":"https://github.com/ReactiveX/RxJS/issues/60","id":94193770,"number":60,"title":"Proposal: Lifted Observable","user":{"login":"trxcllnt","id":178183,"avatar_url":"https://avatars.githubusercontent.com/u/178183?v=3","gravatar_id":"","url":"https://api.github.com/users/trxcllnt","html_url":"https://github.com/trxcllnt","followers_url":"https://api.github.com/users/trxcllnt/followers","following_url":"https://api.github.com/users/trxcllnt/following{/other_user}","gists_url":"https://api.github.com/users/trxcllnt/gists{/gist_id}","starred_url":"https://api.github.com/users/trxcllnt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/trxcllnt/subscriptions","organizations_url":"https://api.github.com/users/trxcllnt/orgs","repos_url":"https://api.github.com/users/trxcllnt/repos","events_url":"https://api.github.com/users/trxcllnt/events{/privacy}","received_events_url":"https://api.github.com/users/trxcllnt/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":{"login":"blesh","id":1540597,"avatar_url":"https://avatars.githubusercontent.com/u/1540597?v=3","gravatar_id":"","url":"https://api.github.com/users/blesh","html_url":"https://github.com/blesh","followers_url":"https://api.github.com/users/blesh/followers","following_url":"https://api.github.com/users/blesh/following{/other_user}","gists_url":"https://api.github.com/users/blesh/gists{/gist_id}","starred_url":"https://api.github.com/users/blesh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/blesh/subscriptions","organizations_url":"https://api.github.com/users/blesh/orgs","repos_url":"https://api.github.com/users/blesh/repos","events_url":"https://api.github.com/users/blesh/events{/privacy}","received_events_url":"https://api.github.com/users/blesh/received_events","type":"User","site_admin":false},"milestone":{"url":"https://api.github.com/repos/ReactiveX/RxJS/milestones/1","html_url":"https://github.com/ReactiveX/RxJS/milestones/Stable%20base%20and%20infrastructure","labels_url":"https://api.github.com/repos/ReactiveX/RxJS/milestones/1/labels","id":1134892,"number":1,"title":"Stable base and infrastructure","description":"A basic observable with standard operators, with passing unit tests, reasonable build rules, and a small of benchmarks comparing against RxJS 2.","creator":{"login":"jeffbcross","id":463703,"avatar_url":"https://avatars.githubusercontent.com/u/463703?v=3","gravatar_id":"","url":"https://api.github.com/users/jeffbcross","html_url":"https://github.com/jeffbcross","followers_url":"https://api.github.com/users/jeffbcross/followers","following_url":"https://api.github.com/users/jeffbcross/following{/other_user}","gists_url":"https://api.github.com/users/jeffbcross/gists{/gist_id}","starred_url":"https://api.github.com/users/jeffbcross/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jeffbcross/subscriptions","organizations_url":"https://api.github.com/users/jeffbcross/orgs","repos_url":"https://api.github.com/users/jeffbcross/repos","events_url":"https://api.github.com/users/jeffbcross/events{/privacy}","received_events_url":"https://api.github.com/users/jeffbcross/received_events","type":"User","site_admin":false},"open_issues":0,"closed_issues":20,"state":"open","created_at":"2015-05-26T22:49:41Z","updated_at":"2015-09-17T20:13:35Z","due_on":null,"closed_at":null},"comments":17,"created_at":"2015-07-10T01:54:22Z","updated_at":"2016-03-03T02:59:59Z","closed_at":"2015-07-17T22:09:28Z","body":"Implement Observable operators in terms of `lift`.\r\n\r\n##### What is `lift`?\r\n`lift` is a function that takes a source Observable and an Observer factory function, and returns a new Observable:\r\n```es6\r\nfunction lift (Observable source, Function observerFactory) {\r\n    return new Observable((destinationObserver) => {\r\n        return source.subscribe(observerFactory(destinationObserver));\r\n    });\r\n}\r\n```\r\n\r\nThough this is the formal definition, we should make the following changes to our Observable's `lift`:\r\n\r\n1. Assign `lift` on the Observable prototype.\r\n2. Remove the `source` argument in favor of using `this` as the source.\r\n3. Change the type of the `observerFactory` from `function` to the `ObserverFactory` interface. This interface requires the implementor to have a `create` function that accepts an Observer and returns an Observer.\r\n\r\n`lift` has the following advantages:\r\n\r\n1. A reduction in the Observable subscription call-stack.\r\n2. Completely factors out transient closures from Observable creation and subscription.\r\n3. Operations performed on Observable subclasses can return the sub type if the implementor overrides `lift` on their Observable subclass.\r\n\r\nFor example, here's how `map` is implemented in terms of `lift`:\r\n```es6\r\nclass Observable {\r\n  constructor(subscribe) {\r\n    if(subscribe) {\r\n      this.subscribe = subscribe;\r\n    }\r\n  }\r\n  subscribe(observer) {\r\n    return this.source.subscribe(this.observerFactory.create(observer));\r\n  }\r\n  lift(observerFactory) {\r\n    const o = new Observable();\r\n    o.source = this;\r\n    o.observerFactory = observerFactory;\r\n    return o;\r\n  }\r\n  map(selector) {\r\n    return this.lift(new MapObserverFactory(selector));\r\n  }\r\n}\r\n\r\nclass MapObserverFactory {\r\n  constructor(selector) {\r\n    this.selector = selector;\r\n  }\r\n  create(destination) {\r\n    return new MapObserver(destination, this.selector);\r\n  }\r\n}\r\n\r\nclass MapObserver {\r\n  constructor(destination, selector) {\r\n    this.selector = selector;\r\n    this.destination = destination;\r\n  }\r\n  next(x) {\r\n    return this.destination.next(this.selector(x));\r\n  }\r\n  throw(e) {\r\n    return this.destination.throw(e);\r\n  }\r\n  return(e) {\r\n    return this.destination.return(e);\r\n  }\r\n}\r\n```"},"comment":{"url":"https://api.github.com/repos/ReactiveX/RxJS/issues/comments/191556252","html_url":"https://github.com/ReactiveX/RxJS/issues/60#issuecomment-191556252","issue_url":"https://api.github.com/repos/ReactiveX/RxJS/issues/60","id":191556252,"user":{"login":"trxcllnt","id":178183,"avatar_url":"https://avatars.githubusercontent.com/u/178183?v=3","gravatar_id":"","url":"https://api.github.com/users/trxcllnt","html_url":"https://github.com/trxcllnt","followers_url":"https://api.github.com/users/trxcllnt/followers","following_url":"https://api.github.com/users/trxcllnt/following{/other_user}","gists_url":"https://api.github.com/users/trxcllnt/gists{/gist_id}","starred_url":"https://api.github.com/users/trxcllnt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/trxcllnt/subscriptions","organizations_url":"https://api.github.com/users/trxcllnt/orgs","repos_url":"https://api.github.com/users/trxcllnt/repos","events_url":"https://api.github.com/users/trxcllnt/events{/privacy}","received_events_url":"https://api.github.com/users/trxcllnt/received_events","type":"User","site_admin":false},"created_at":"2016-03-03T02:59:59Z","updated_at":"2016-03-03T02:59:59Z","body":"@EmmanuelOga yep, pretty much identical"}}