Nesting Iterator Functions

Example of functional programming in JavaScript

by Patrick Hund

CSS

body {
    background-color: #000000;
    padding: 10px;
    font-family: monospace;
}

p {
    margin: 0;
    color: green;
}

p.new {
    color: lime;
}

JavaScript

var roman,
    arabic,
    alpha;

function log() {
    var $body = $("body"),
        $doc = $(document),
        msg = "", i;

    for (i = 0; i < arguments.length; i++) {
        msg += (arguments[i] + (i === arguments.length - 1 ? "" : " "));
    }
    $body.find("p").last().removeClass("new");
    $body.append("<p class=\"new\">" + msg + "</p>");
    $doc.scrollTop($body.prop("scrollHeight"));
}

function nest() {
    var functions = arguments,
        findex = functions.length - 1,
        f = functions[findex];

    while (--findex >= 0) {
        f = functions[findex](f);
    }
    f();
}

function iterate() {
    var slice = Array.prototype.slice,
        items = [],
        i;

    for (i = 0; i < arguments.length; i++) {
        items = items.concat(arguments[i]);
    }

    return function (callback) {
        return function() {
            var prev = slice.apply(arguments),
                i;
            for (i = 0; i < items.length; i++) {
                if (typeof callback === "function") {
                    callback.apply(null, prev.concat(items[i]));
                }
            }
        };
    };
}

roman = iterate("I", "II", "III"); // you can pass items as variable number of arguments
arabic = iterate(["1.", "2.", "3."]); // you can also pass items as array
alpha = iterate(["a)", "b)"], "c)", ["d)"]); // you can mix both methods of passing items

nest(roman, arabic, alpha, log); // same result as: roman(arabic(alpha(log)))();