// 末尾再帰の最適化はブラウザ上のJavaScriptでは基本的に行われないため、スタックオーバーフローが発生します
/**
* @param {number} n
* @param {Function} f
* @returns 0
*/
const fFor1 = (n, f) => {
if (n <= 0) return n;
f(n - 1);
return fFor1(n - 1, f);
};
console.log("> " + fFor1(5, n => console.log(n)));
/**
* @param {number} from
* @param {number} to
* @param {Function} f
* @returns to
*/
const fFor2 = (from, to, f) => {
if (from >= to) return from;
f(from);
return fFor2(from + 1, to, f);
};
console.log("> " + fFor2(2, 6, n => console.log(n)));
/**
* @param {number} initialization
* @param {Function} condition predicate
* @param {Function} afterthought
* @param {Function} f
* @returns The last value that was not operated on by f
*/
const fFor3 = (initialization, condition, afterthought, f) => {
if (!condition(initialization)) return initialization;
f(initialization);
return fFor3(afterthought(initialization), condition, afterthought, f);
};
console.log("> " + fFor3(10, n => n < 15, n => ++n, n => console.log(n)));
const fWhile = (condition, f) => {
if (!condition(f())) return;
fWhile(condition, f);
};