Generate a sequence of primes. Limit that sequence to primes below the specified amount if provided, otherwise generate an infinite sequence of primes
(Will become progressively more performance intensive for each prime)
function primes(limit) {
    if (limit != null) {
        // https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
        return defer(function* () {
            let set = Array.from(range(3, (limit / 2) - 1, 2));
            let curr = 3;
            const sqrtLimit = Math.sqrt(limit);
            yield 2;
            let lastIndex = 0;
            while (curr <= sqrtLimit) {
                yield curr;
                set = set.splice(0, lastIndex).concat(set.splice(lastIndex + 1).filter(s => s % curr !== 0));
                lastIndex = set.findIndex(s => s > curr);
                if (lastIndex == null) {
                    return;
                }
                curr = set[lastIndex];
            }
            yield curr;
            yield* set.slice(lastIndex + 1);
        });
    }
    return defer(function* () {
        const previousPrimes = [2, 3];
        yield 2;
        yield 3;
        for (let curr = 5;; curr += 2) {
            let allowed = true;
            const sqrt = Math.sqrt(curr);
            for (const prime of previousPrimes) {
                if (prime > sqrt) {
                    break;
                }
                else if (curr % prime === 0) {
                    allowed = false;
                    break;
                }
            }
            if (allowed) {
                previousPrimes.push(curr);
                yield curr;
            }
        }
    });
}