Skip to content

Instantly share code, notes, and snippets.

@PaulMaynard
Last active May 2, 2016 16:13
Show Gist options
  • Save PaulMaynard/c4c509889ba8869bf320 to your computer and use it in GitHub Desktop.
Save PaulMaynard/c4c509889ba8869bf320 to your computer and use it in GitHub Desktop.
Generator and Iterator manipulation
/** Sample die roller */
function die(pattern) {
let [, sign = '+', amt = 1, sides = 6, num, mod] = die.regex.exec(pattern)
let gen
if (num) {
gen = _.fill(Number(num))
} else {
let die = _.func(() => Math.floor(Math.random() * sides) + 1)
gen = _.combine(sum, ...Array(amt).fill(die))
}
gen = _.map(die.signs[sign], gen)
if(mod) {
return _.combine(sum, gen, die(mod))
} else {
return gen
}
}
die.regex = /^([+-])?(?:(?:(\d*))?d(\d+)|(\d+))((?:[+-](?:(?:\d*d)?\d+|\d+))*)$/i
die.signs = {
'+': n => n,
'-': n => -n,
}
function sum(a, ...b) {
if (b.length) {
return a + sum(...b)
} else {
return a
}
}
/**
* Eater.js version: 0.3.4
* Usage examples:
* // Even squares of numbers between 1-100
* _(_.filter( x => x % 2 === 0, _.map(x => x * x, _.range(1, 100))))
* // 10 coin flips
* _(_.pick([true, false]), 10)
* // first 100 Fibonacci numbers (assuming already defined generator)
* _(_.take(100, fibonacci()))
* // Consume pseudo-array
* _({0: 1, 1: 2, length: 2})
*/
window._ = window.eater = (function(){'use strict';
function eater(it, ...args) {
if(typeof it === 'function') {
return eater.func(it, ...args);
} else if(it[Symbol.iterator]) {
if(typeof args[0] === 'number'|| args[0] instanceof Number) {
return [...eater.take(args[0], it)];
} else {
return [...it];
}
} else if(it.next) {
return eater.take(it);
} else if(typeof it.length === 'number') {
return eater.loop(it);
} else {
return eater.fill(it);
}
}
Object.assign(eater, {
/* Creators */
*range(start = Infinity, end = null) {
if(end == null) {
[start, end] = [1, start];
}
for(let i = start; i <= end; i++) {
yield i;
}
},
*fill(val) {
while(true) {
yield val;
}
},
*func(fn, ...args) {
while(true) {
yield fn(...args);
}
},
*loop(it) {
for(let i = 0; i < it.length; i++) {
yield it[i];
}
},
*pick(a) {
while(true) {
yield a[Math.floor(Math.random() * a.length)];
}
},
*join(...its) {
for(let it of its) {
yield* it;
}
},
/* Accessors */
*take(amt, iter) {
if(iter == null) {
iter = amt;
amt = Infinity;
}
let it = iter[Symbol.iterator] ? iter[Symbol.iterator]() : iter
for(let i = 0, n; i < amt && !((n = it.next()).done); i++) {
yield n.value;
}
},
each(fun, it) {
if(it == null) {
return i => each(fun, i);
} else {
return each(fun, it);
}
},
get(it) {
return it.next().value;
},
taker(amt, it) {
if(it == null) {
it = amt;
amt = 1;
}
return () => eater.take(amt, it);
},
reduce(fun, val, it) {
if(it == null) {
return i => reduce(fun, val, i);
} else {
return reduce(fun, val, it)
}
},
/* Manipulators */
map(fun, it) {
if(it == null) {
return i => map(fun, i);
} else {
return map(fun, it);
}
},
filter(fun, it) {
if(it == null) {
return i => filter(fun, i);
} else {
return filter(fun, it);
}
},
combine(fun, ...its) {
if(its.length === 0) {
return (...i) => combine(fun, i);
} else {
return combine(fun, ...its);
}
}
});
function* each(fun, it) {
for(let i of it) {
fun(i);
yield i;
}
}
function reduce(fun, val, it) {
for(let i of it) {
val = fun(val, i);
}
return val
}
function* map(fun, it) {
for(let i of it) {
yield fun(i);
}
}
function* filter(fun, it) {
for(let i of it) {
if(fun(i)) {
yield i;
}
}
}
function* combine(fun, ...its) {
while(true) {
let results = its.map(i => i.next());
let done = results.every(r => r.done);
if(done) {
break;
} else {
yield fun(...results.map(r => r.value));
}
}
}
return eater;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment