Skip to content

Instantly share code, notes, and snippets.

@martianboy
Last active August 29, 2015 14:04
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save martianboy/92a367009dcc10515b44 to your computer and use it in GitHub Desktop.
Save martianboy/92a367009dcc10515b44 to your computer and use it in GitHub Desktop.
Testing higher-order functions with es6 generators
/* This will run async without creating intermediate arrays. */
function* makeGeneratorFromArray(array){
var nextIndex = 0;
while(nextIndex < array.length) {
yield array[nextIndex++];
}
}
function GeneratorsWrapper(input) {
if (Array.isArray(input))
this._internalGenerator = makeGeneratorFromArray(input);
else if (input.isGenerator && input.isGenerator())
this._internalGenerator = input();
else
throw new TypeError('Unidentifiable input.')
}
GeneratorsWrapper.prototype.each = function(fn, context) {
if (typeof fn !== 'function')
throw new TypeError('callback is not a function.');
var index = 0;
for (var x of this._internalGenerator) {
fn.call(context, x, index++, this);
}
}
GeneratorsWrapper.prototype.map = function(fn, context) {
if (typeof fn !== 'function')
throw new TypeError('callback is not a function.');
var _internalGenerator = this._internalGenerator;
return new GeneratorsWrapper(function* () {
var index = 0;
for (var x of _internalGenerator) {
yield fn.call(context, x, index++, this);
}
});
}
GeneratorsWrapper.prototype.filter = function (fn, context) {
if (typeof fn !== 'function')
throw new TypeError('callback is not a function.');
var _internalGenerator = this._internalGenerator;
return new GeneratorsWrapper(function* () {
var index = 0;
for (var x of _internalGenerator) {
if (fn.call(context, x, index++, this)) {
yield x;
}
}
});
}
GeneratorsWrapper.prototype.reduce = function(fn, initialValue) {
if (typeof fn !== 'function')
throw new TypeError('callback is not a function.');
var index = 0;
var accumulator;
var genVal = this._internalGenerator.next();
if (genVal.done)
throw new TypeError('This generator is done for!');
if (initialValue)
accumulator = initialValue;
else
accumulator = genVal.value;
while(!genVal.done) {
accumulator = fn.call(undefined, accumulator, genVal.value, index, this);
genVal = this._internalGenerator.next();
}
return accumulator;
}
GeneratorsWrapper.prototype.take = function (n) {
if (n < 1)
throw new TypeError('Can\'t take zero or less items!');
var _internalGenerator = this._internalGenerator;
return new GeneratorsWrapper(function* () {
var genVal = _internalGenerator.next();
for(var i = 0; (i < n) && !genVal.done; i++) {
yield genVal.value;
genVal = _internalGenerator.next();
}
});
};
GeneratorsWrapper.prototype.first = function() {
return this.take(1);
}
GeneratorsWrapper.prototype.toArray = function() {
return this.reduce(function(arr, elem) {
arr.push(elem);
return arr;
}, []);
}
GeneratorsWrapper.prototype.single = function() {
var arr = this.toArray();
if (arr.length)
return arr[0];
else
throw new Error('Generator is empty.');
}
module.exports = GeneratorsWrapper;
var Generator = require('./generators');
/************************************************
* Fibonacci Sequence & Golden Ratio *
************************************************/
console.log(
new Generator([1,2,3,4,5,6])
.map(function(x) { return x * x; })
.filter(function(x) { return x > 10; })
.toArray()
);
/************************************************
* Fibonacci Sequence & Golden Ratio *
************************************************/
function *fibonacci() {
var x1 = 0, x2 = 1;
while(true) {
x2 += x1;
x1 = x2 - x1;
yield x1;
}
}
var previous;
new Generator(fibonacci)
.take(26)
.each(function(x) {
if (previous)
console.log((previous + x) / x);
previous = x;
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment