var cycle = function(a, n, fn, context) {
    var length = a.length;
    var i = 0;
    
    while (n > 0) {
        n -= 1;
        fn.call(context, a[i], i, a);
        i = (i + 1) % length;
    }
};

var distinct = function(a, fn, context) {
    var length = a.length;
    var i;
    var seen = new Set();

    for (i = 0; i < length; i += 1) {
        if (!(seen.has(a[i]))) {
            seen.add(a[i]);
            fn.call(context, a[i], i, a);
        }
    }
};

var product = function(a, b, fn, context) {
    var i, j;
    var aLength = a.length;
    var bLength = b.length;

    for (i = 0; i < aLength; i += 1) {
        for (j = 0; j < bLength; j += 1) {
            fn.call(context, a[i], b[j], i, j, a);
        }
    }
};

var repeat = function(n, fn, context) {
    var i;
    
    for (i = 0; i < n; i += 1) {
        fn.call(context, i);
    }
};

var slices = function(a, n, fn, context) {
    var i;
    var times = Math.ceil(a.length/n);

    for (i = 0; i < times; i += 1) {
        fn.call(context, a.slice(i*n, (i+1)*n), i, a);
    };
};

var subsets = function(a, size, fn, context) {
    if (a == null) {
        return [];
    }

    var ret = [];
    var i, j, k;
    var length = a.length;

    ret.push([]);
};

var takeNth = function(a, n, fn, context) {
    var length = a.length;
    var i;

    for (i = n-1; i < length; i += n) {
        fn.call(context, a[i], i, a);
    }
};

module.exports = {
    cycle: cycle,
    distinct: distinct,
    product: product,
    repeat: repeat,
    slices: slices,
    takeNth: takeNth
};

@@ -783,21 +783,121 @@
  var i;%0A
+%0A
     
-%0A
+if (n == null) %7B%0A        while (true) %7B%0A            fn.call(context, i);%0A        %7D%0A    %7D else %7B%0A    
     for 
@@ -921,32 +921,36 @@
 += 1) %7B%0A        
+    
 fn.call(context,
@@ -950,24 +950,34 @@
 ontext, i);%0A
+        %7D%0A
     %7D%0A%7D;%0A%0Ava
@@ -1346,24 +1346,185 @@
 sh(%5B%5D);%0A%7D;%0A%0A
+var takeStrict = function(a, n) %7B%0A    if (a.length %3C n) %7B%0A        throw new Error('array does not have enough elements');%0A    %7D%0A%0A    return a.slice(0, n+1);%0A%7D;%0A%0A
 var takeNth 

Allow repeat to run infinitely if argument is null