Generators in JavaScript: A Lazy Zip

In [60]:
function *zip(...[first, ...iterables]){
    const length = iterables.length;
    let item;    
    while(true){
        item = first.next();
        if (item.done) break;
        const acc = [];
        for(let i = 0; i < length; i++){
            const item_ = iterables[i].next();
            acc.push(item_.value);
        }
        yield [item.value, ...acc];
    }
}
In [61]:
function *iter(item){
    yield* Array.from(item);
}
In [108]:
function *range(start, stop, step=1){
    if(step < 1) throw new Error('step must be 1 or greater.');
    if(stop <= start) throw new Error('stop must be larger than start');
    yield* Array.from({length: ((stop - start) / step)}, (_, i) => start + (i * step));
}

Convenient method to remember where the letter 'A' or 'a' starts in ASCII table.

ASCII uses the last 7 bits of a byte (8 bits): 00000000

Set the first bit to '0' and the second bit to '1'.

Set all except the last bit to 0.

Set the last bit to 1.

01000001

That makes 65.

Set the third bit to 1 and that makes 97.

01100001

I learned this tidbit here:

Characters, Symbols, and the Unicode Miracle

In [126]:
var [UPPERCASE, LOWERCASE] = [
    0b01000001, // 65
    0b01100001, // 97
].map(n => String.fromCharCode(...range(n, n+26)))
In [127]:
for (let item of zip(range(0, 26, 1), iter(UPPERCASE), iter(LOWERCASE))){
    console.log(item);
}
[ 0, 'A', 'a' ]
[ 1, 'B', 'b' ]
[ 2, 'C', 'c' ]
[ 3, 'D', 'd' ]
[ 4, 'E', 'e' ]
[ 5, 'F', 'f' ]
[ 6, 'G', 'g' ]
[ 7, 'H', 'h' ]
[ 8, 'I', 'i' ]
[ 9, 'J', 'j' ]
[ 10, 'K', 'k' ]
[ 11, 'L', 'l' ]
[ 12, 'M', 'm' ]
[ 13, 'N', 'n' ]
[ 14, 'O', 'o' ]
[ 15, 'P', 'p' ]
[ 16, 'Q', 'q' ]
[ 17, 'R', 'r' ]
[ 18, 'S', 's' ]
[ 19, 'T', 't' ]
[ 20, 'U', 'u' ]
[ 21, 'V', 'v' ]
[ 22, 'W', 'w' ]
[ 23, 'X', 'x' ]
[ 24, 'Y', 'y' ]
[ 25, 'Z', 'z' ]