Проблема в codewars.com:
https://www.codewars.com/kata/foldr/train/javascript
Определить функцию свёртки для массива, которая реализует ту же функцию, что и встроенная функция reduRight (). Проблема очень абстрактная, потому что я мало знал о функциональном программировании.
Я считаю, что наиболее важным является реализация отложенной оценки в JavaScript. Но я не знаю, как с этим справиться.
Например, у нас есть две функции: indexOf
и logging
, indexOf(x)
- это функция, которая будет вызываться в качестве аргументов в методе foldr
, logging
- это функция-обертка, которая сообщает нам, сколько раз indexOf(x)
можно назвать.
const indexOf = y => function (cur, acc) {
if (cur === y) {
return 0
} else {
return acc + 1 || -1
}
};
const logging = fn => function logging(...a) {
i++;
return fn(...a);
};
Если мы реализуем это без лени и используем рекурсию:
Object.defineProperty(Array.prototype, "foldr", {
value: function foldr(fn, z) {
return function _foldr(a) {
if (a.length === 0) {
return z
}
return fn(a[0], _foldr(a.slice(1)))
}(this);
}
});
let i = 0
let x = [1, 2, 3].foldr(logging(indexOf(1)), -1)
console.log(`x: ${x}`) // x: 0
console.log(`i: ${i}`) // i: 3
Переменная i
показывает, что функция была вызвана 3 раза, весь массив был повторен. Однако, если мы наблюдаем функцию indexOf
, мы обнаружим, что нам не нужно итерировать весь массив, если мы используем ленивую оценку.
На первом уровне рекурсии
indexOf(1)(a[0], _foldr(a.slice(1)))
равно indexOf(1)(1, _foldr([2,3]))
, потому что cur === y
, он должен немедленно возвратить 0 и не нужно оценивать второй аргумент _foldr([2,3])
. Таким образом, в тестовом примере codewars.com, i
должно быть 1.
Как я мог справиться с этим?