Skip to content

Instantly share code, notes, and snippets.

@nodew
Last active August 7, 2018 09:16
Show Gist options
  • Save nodew/e0e62d8de7c083f2e5a7b5d5fb7934ff to your computer and use it in GitHub Desktop.
Save nodew/e0e62d8de7c083f2e5a7b5d5fb7934ff to your computer and use it in GitHub Desktop.
lazy list implementation with generators
function wrap(iterator) {
const sequence = [];
const next = (i) => {
if (sequence.length > i) {
return {
value: sequence[i],
done: false
}
}
const { value, done } = iterator.next();
if (!done) {
sequence.push(value);
}
return {
value,
done
}
}
return {
[Symbol.iterator]: function () {
let i = -1;
return {
next: function () {
i++;
return next(i)
}
}
},
next
}
}
const repeat = (item) => wrap(function* () {
while (true) {
yield item
}
}())
const cycle = (items) => wrap(function* () {
const lst = Array.from(items)
while (true) {
for (let item of lst) {
yield item
}
}
}())
const iterate = (fn, initial) => wrap(function* () {
let val = initial
while (true) {
yield val
val = fn(val)
}
}())
const range = (start, end = Infinity, step = 1) => wrap(function* () {
while (start <= end) {
yield start
start += step
}
})
const replicate = (item, count) => {
return take(repeat(item), count);
}
const map = (fn, items) => wrap(function* () {
for (let item of items) {
yield fn(item)
}
}())
const filter = (predicate, items) => wrap(function *() {
for (let item of items) {
if (predicate(item)) {
yield item
}
}
}())
const take = (n, items) => wrap(function* () {
let i = 0
if (n < 1) return
for (let item of items) {
yield item
i++
if (i >= n) {
return
}
}
}())
const takeWhile = (predicate, items) => wrap(function* () {
for (let item of items) {
if (predicate(item)) {
yield item
} else {
return
}
}
}())
const drop = (n, items) => wrap(function* () {
let i = 0
for (let item of items) {
if (i >= n) {
yield item
}
i++
}
}())
const head = (items) => {
for (let item of items) {
return item;
}
}
const tail = (items) => wrap(function* () {
let visited = false;
for (let item of items) {
if (visited) {
yield item;
} else {
visited = true
}
}
}())
const size = (items) => {
let count = 0
for (let item of items) {
count++
}
return count;
}
// --------------------------------
const fib = (a, b) => wrap(function* () {
let c = 0
yield a
yield b
while (true) {
c = a + b
a = b
b = c
yield c
}
}())
const fibnacci = fib(1, 1);
console.time('first')
console.log(size(take(100, fibnacci)))
console.timeEnd('first')
console.time('second')
console.log(size(take(20, drop(10, tail(fibnacci)))))
console.timeEnd('second')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment