Skip to content

Instantly share code, notes, and snippets.

@briancavalier
Last active November 24, 2021 20:10
Show Gist options
  • Select an option

  • Save briancavalier/abc713b6806f37c687a6 to your computer and use it in GitHub Desktop.

Select an option

Save briancavalier/abc713b6806f37c687a6 to your computer and use it in GitHub Desktop.

Revisions

  1. briancavalier revised this gist May 6, 2014. 1 changed file with 3 additions and 9 deletions.
    12 changes: 3 additions & 9 deletions list-out-of-yield.js
    Original file line number Diff line number Diff line change
    @@ -18,9 +18,7 @@ export function* concat(a, b) {

    // infinite list of x, f(x), f(f(x)), etc.
    export function* iterate(f, x) {
    yield* unfold(function(x) {
    return [x, f(x)];
    }, x);
    yield* unfold(x => [x, f(x)], x);
    }

    // infinite list by unfolding f, starting with x
    @@ -65,9 +63,7 @@ export function* scanl(f, z, list) {

    // list containing at most first n elements
    export function* take(n, list) {
    yield* takeWhile(function() {
    return --n >= 0;
    }, list);
    yield* takeWhile(() => --n >= 0, list);
    }

    export function* takeWhile(f, list) {
    @@ -80,9 +76,7 @@ export function* takeWhile(f, list) {
    }

    export function* drop(n, list) {
    yield* dropWhile(function() {
    return --n > 0;
    }, list);
    yield* dropWhile(() => --n > 0, list);
    }

    export function* dropWhile(f, list) {
  2. briancavalier created this gist May 6, 2014.
    10 changes: 10 additions & 0 deletions example.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,10 @@
    // Requires traceur

    import { iterate, take, map, foldl } from './list-out-of-yield';

    // Sum of squares of integers 1..100
    var values = take(100, iterate(x => x + 1, 1));

    var result = foldl((x, y) => x + y, 0, map(x => x * x, values));

    console.log(result);
    128 changes: 128 additions & 0 deletions list-out-of-yield.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,128 @@
    // empty list
    export function* empty() {}

    // list containing all arguments
    export function* list(...xs) {
    yield* xs;
    }

    // list with head x, tail list
    export function* cons(x, list) {
    yield x, yield* list;
    }

    // concat lists a and b
    export function* concat(a, b) {
    yield* a, yield* b;
    }

    // infinite list of x, f(x), f(f(x)), etc.
    export function* iterate(f, x) {
    yield* unfold(function(x) {
    return [x, f(x)];
    }, x);
    }

    // infinite list by unfolding f, starting with x
    export function* unfold(f, x) {
    // No tail recursion yet, will blow the stack, oh well.
    // See https://github.com/google/traceur-compiler/issues/218
    var [a, b] = f(x);
    yield a, yield* unfold(f, b);
    }

    // infinite list of xs
    export function* repeat(x) {
    yield x, yield* repeat(x);
    }

    // fold list from the left
    export function foldl(f, z, list) {
    // This "loop" is a hack just to get the head of the list
    // Is there a better way without resorting to using iterator.next()?
    for(var x of list) {
    return foldl(f, f(z, x), list);
    }
    return z;
    }

    // fold list from the right
    export function foldr(f, z, list) {
    // This "loop" is a hack just to get the head of the list
    // Is there a better way without resorting to using iterator.next()?
    for(var x of list) {
    return f(x, foldr(f, z, list));
    }
    return z;
    }

    export function* scanl(f, z, list) {
    for(var x of list) { // loop :(
    yield z = f(z, x);
    }
    return z;
    }

    // list containing at most first n elements
    export function* take(n, list) {
    yield* takeWhile(function() {
    return --n >= 0;
    }, list);
    }

    export function* takeWhile(f, list) {
    for(var x of list) { // loop :(
    if(!f(x)) {
    break;
    }
    yield x;
    }
    }

    export function* drop(n, list) {
    yield* dropWhile(function() {
    return --n > 0;
    }, list);
    }

    export function* dropWhile(f, list) {
    for(var x of list) { // loop :(
    if(!f(x)) {
    break;
    }
    }

    yield* list;
    }

    // list of items transformed by applying f(x)
    export function* map(f, list) {
    for(var x of list) { // loop :(
    yield f(x);
    }
    }

    // apply all the fs to all the xs
    export function* ap(fs, xs) {
    // WARNING: Doesn't work if xs is a generator iterable, because
    // generator iterables are not restartable
    yield* chain(function*(f) {
    yield* map(f, xs);
    }, fs);
    }

    // aka flatMap/bind
    export function* chain(f, list) {
    for(var x of list) { // loop :(
    yield* f(x);
    }
    }

    // list containing only items where f(x) is truthy
    export function* filter(f, list) {
    for(var x of list) { // loop :(
    if(f(x)) {
    yield x;
    }
    }
    }