Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save raganwald/702d4a24b1bdff9f9c1789c85b1f6979 to your computer and use it in GitHub Desktop.
Save raganwald/702d4a24b1bdff9f9c1789c85b1f6979 to your computer and use it in GitHub Desktop.
function * just (...values) {
yield * values;
};
function first (iterable) {
const iterator = iterable[Symbol.iterator]();
const { done, value } = iterator.next();
if (!done) return value;
};
function * rest (iterable) {
const iterator = iterable[Symbol.iterator]();
iterator.next()
yield * iterator;
};
function split (iterable) {
const iterator = iterable[Symbol.iterator]();
const { done, value: first } = iterator.next();
if (done) {
return { rest: [] };
} else {
return { first, rest: iterator };
}
};
function * join (first, rest) {
yield first;
yield * rest;
};
function * take (numberToTake, iterable) {
const iterator = iterable[Symbol.iterator]();
for (let i = 0; i < numberToTake; ++i) {
const { done, value } = iterator.next();
if (done) return;
else yield value;
}
}
function * infiniteNumberOf (something) {
while (true) {
yield something;
}
}
function * from (number, increment = 1) {
while (true) {
yield number;
number = number + increment;
}
}
function * sequence (value, nextFn = (x) => x) {
while (true) {
yield value;
value = nextFn(value);
}
}
function * sequence2 (first, second, nextFn = (x, y) => y) {
yield first;
while (true) {
yield second;
[first, second] = [second, nextFn(first, second)]
}
}
function * mapWith (fn, ...iterables) {
const iterators = iterables.map((iterable) => iterable[Symbol.iterator]());
while (true) {
const pairs = iterators.map((iterator) => iterator.next());
const values = pairs.map((pair) => pair.value);
const dones = pairs.map((pair) => pair.done);
if (dones.find((done) => done)) {
return;
} else {
yield fn(...values);
}
}
}
function * filterWith (fn, iterable) {
const iterator = iterable[Symbol.iterator]();
while (true) {
const { value, done } = iterator.next();
if (done) {
return;
} else if (fn(value)) {
yield value;
}
}
}
function * slices (length, iterable) {
const iterator = iterable[Symbol.iterator]();
let buffer = [...take(length, iterator)];
if (buffer.length < length) return;
let nextElementIndex = 0;
while (true) {
yield buffer;
const { value, done } = iterator.next();
if (done) return;
buffer = buffer.slice(1);
buffer.push(value);
}
}
// __Examples__
const skit = infiniteNumberOf('spam');
const powersOfTwo = sequence(2, (x) => x * 2);
const squares = mapWith((x) => x*x, from(1));
const odds = filterWith((x) => x % 2 === 1, from(1));
function * primes (numbers = from(2)) {
while (true) {
const { first, rest } = split(numbers);
yield first;
numbers = filterWith((n) => n % first !== 0, rest);
}
}
const greetings = mapWith(
(x, y) => `${x} ${y}`,
['hello', 'bonjour', 'hej'],
['frank', 'pascal', 'rognvoldr']
);
const fibonacci = sequence2(0, 1, (x, y) => x + y);
function * fibonacci2 () {
yield 0;
yield 1;
yield * mapWith(
(x, y) => x + y,
fibonacci2(),
rest(fibonacci2())
);
}
function * fibonacci3 () {
yield 0;
yield 1;
yield * mapWith(
([x, y]) => x + y,
slices(2, fibonacci3())
);
};
function * phi () {
yield * rest(
mapWith(
(x, y) => x / y,
rest(fibonacci()),
fibonacci()
)
);
}
function * phi2 () {
yield * rest(
mapWith(
([x, y]) => x / y,
slices(2, fibonacci3())
)
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment