functional for-loop

by Csaba Hellinger

HTML

Functional:
<ul>
    <li>No variables</li>
    <li>No mutation</li>
    <li>No side effects</li>
    <li>No loops</li>
    <li>Recursion with proper tail call</li>
</ul>
Features:
<ul>
    <li>Integer or float</li>
    <li>Forward or backward</li>
    <li>Protected against infinite loops</li>
</ul>
(Results on the console)

CSS

ul {
    margin-top: 0;
}

JavaScript

function isNumber(n) {
	return isFinite(n) && +n === n;
}

function funcFor(first, last, step, callback) {
	// check params
    if (!(isNumber(first) && isNumber(last) && isNumber(step))) {
    	throw 'first/last/step should be finite numbers.';
    }
    if (typeof callback !== 'function') {
    	throw 'callback should be a function, with a single index parameter.';
    }
	if (step === 0) {
    	throw 'step shouldn\'t be zero. it would lead to infinite loop.';
    }
    if ((step > 0 && first > last) || (step < 0 && first < last)) {
    	throw 'invalid first/last/step combination. it would lead to infinite loop.';
    }
    // recursive inner function
    function inner(index) {
        if ((step > 0 && index > last) || (step < 0 && index < last)) {
            console.log('end.');
            return;
        } 
        callback(index);
        // next (proper tail call)
        inner(index + step);
    }
    // start with the first 
    inner(first);
}

// try it out
funcFor(1, 10, 1, function (index) {
	console.log(`index: ${index}`);
});