Skip to content

Instantly share code, notes, and snippets.

@xphere
Last active August 29, 2015 13:56
Show Gist options
  • Select an option

  • Save xphere/9096370 to your computer and use it in GitHub Desktop.

Select an option

Save xphere/9096370 to your computer and use it in GitHub Desktop.
Streams javascript naïve implementation
var Stream = (function () {
var undefined, empty, proto;
function extend(dest, source) {
for (var arg = 1; arg < arguments.length; ++arg) {
for (var key in arguments[arg]) {
if (arguments[arg].hasOwnProperty(key)) {
dest[key] = arguments[arg][key];
}
}
}
return dest;
}
function Stream(head, tail) {
this._head = head;
this._tail = undefined === tail ? empty : tail;
}
extend(Stream.prototype, {
isEmpty: function () {
return undefined === this._head;
},
head: function () {
if (this.isEmpty()) { throw new Error("Can't get head of empty stream"); }
return this._head;
},
tail: function () {
if (this.isEmpty()) { throw new Error("Can't get tail of empty stream"); }
return undefined === this._resolvedTail
? this._resolvedTail = this._tail()
: this._resolvedTail;
},
item: function (n) {
return 0 === n || undefined === n ? this.head() : this.tail().item(n - 1);
},
take: function (n) {
return 0 === n ? empty() : new Stream(this._head, function () {
return this.tail().take(n - 1);
}.bind(this));
},
skip: function (n) {
(undefined === n) && (n = 1);
return 0 === n ? this : (this.isEmpty() ? empty() : this.tail().skip(n - 1));
},
append: function (stream) {
return this.isEmpty() ? stream : new Stream(this.head(), function () {
return this.tail().append(stream);
}.bind(this));
},
map: function (fn) {
return this.isEmpty() ? this : new Stream(fn(this.head()), function () {
return this.tail().map(fn);
}.bind(this));
},
//
// These methods need a finite stream
//
length: function () {
return !this.isEmpty() ? 1 + this._tail().length() : 0;
},
reduce: function (fn, acc) {
return !this.isEmpty() ? this.tail().reduce(fn, fn(acc, this.head())) : acc;
}
});
extend(Stream, {
empty: empty = function () {
return new Stream();
},
make: function () {
return Stream.fromArray(Array.prototype.slice.apply(arguments));
},
fromArray: function (data) {
if (0 === data.length) { return empty(); }
return new Stream(data[0], function () {
return Stream.fromArray(data.slice(1));
})
}
});
return Stream;
}());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment