Last active
December 27, 2015 10:39
-
-
Save mattpodwysocki/7312324 to your computer and use it in GitHub Desktop.
Observable.scan
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Rx.Observable.prototype.scan = function (/* [seed], accumulator */) { | |
var hasSeed = false, seed, accumulator, source = this; | |
if (arguments.length === 2) { | |
hasSeed = true; | |
seed = arguments[0]; | |
accumulator = arguments[1]; | |
} else { | |
accumulator = arguments[0]; | |
} | |
return Rx.Observable.createWithDisposable(function (observer) { | |
var hasAccumulation, accumulation, hasValue; | |
return source.subscribe ( | |
function (x) { | |
try { | |
if (!hasValue) { | |
hasValue = true; | |
} | |
if (hasAccumulation) { | |
accumulation = accumulator(accumulation, x); | |
} else { | |
accumulation = hasSeed ? accumulator(seed, x) : x; | |
hasAccumulation = true; | |
} | |
} catch (e) { | |
observer.onError(e); | |
return; | |
} | |
observer.onNext(accumulation); | |
}, | |
observer.onError.bind(observer), | |
function () { | |
if (!hasValue && hasSeed) { | |
observer.onNext(seed); | |
} | |
observer.onCompleted(); | |
} | |
); | |
}); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function add(x, y) { return x + y; } | |
function createObserver(num) { | |
return Rx.Observer.create( | |
function (x) { | |
console.log('next ' + num + ':' + x); | |
}, | |
function (e) { | |
console.log(e.message); | |
}, | |
function () { | |
console.log('completed ' + num); | |
} | |
); | |
} | |
// Usage | |
var obs1 = Rx.Observable.empty().scan(add); | |
var obs2 = Rx.Observable.empty().scan(0, add); | |
var obs3 = Rx.Observable.range(1, 3).scan(add); | |
var obs4 = Rx.Observable.range(1, 3).scan(0, add); | |
obs1.subscribe(createObserver(1)); | |
// => completed 1 | |
obs2.subscribe(createObserver(2)); | |
// => next 2:0 | |
// => completed 2 | |
obs3.subscribe(createObserver(3)); | |
// => next 3:1 | |
// => next 3:3 | |
// => next 3:6 | |
// => completed 3 | |
obs4.subscribe(createObserver(4)); | |
// => next 4:1 | |
// => next 4:3 | |
// => next 4:6 | |
// => completed 4 |
This is to conform to Haskell:
scanl (+) 0 [] == [0]
scanl1 (+) [] == []
Or even F#:
Seq.empty<int> |> Seq.scan (+) 0
// => [0]
Interesting. And actually, this makes more sense. If there is a seed, the seed is presumably the identity of the function under its parameter types.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The following expected result would break compatibility with the .NET implementation.
// => next 2:0
Is that intentional?
See here: https://gist.github.com/cwharris/7321527