在Javascript中递归调用咖喱函数

时间:2019-03-08 22:49:47

标签: javascript currying pointfree

作为一个玩具示例,可以说我们具有此功能及其用法:

const map = (f = n => n + 1) => (lst = [1,2,3]) => {
    if(lst.length === 0)
        return [];
    else
        return [f(...lst.splice(0,1)), ...map(f)(lst)];
}
const inc = n => n + 1;
const map_inc = map(inc);
map_inc([1,2,3]) // => (produces) [2,3,4]

在咖喱函数映射中,我通过调用map(f)(lst)使用“递归”。

上面的示例在调用该函数之前会先对其进行重建。

是否可以在不重建函数的情况下执行此递归?

我知道这种方式:

y = (f = (f, ...args) => [...args],
     ...args) => f(f, ...args);

const map = (mapper = n => n + 1) => (self = mapper, lst = [1,2,3]) => {
    if(lst.length === 0)
        return [];
    else
        return [mapper(...lst.splice(0,1)), ...self(self, lst)];
}
const inc = n => n + 1;
const map_inc = (...args) => y(map(inc), ...args);
map_inc([1,2,3]) // => (produces) [2,3,4]

我真的不喜欢这需要如何将函数传递给自身。

是否可以在没有y函数的情况下并且不将函数传递给自身?可以以一种更加没有意义的方式来做到这一点吗?

2 个答案:

答案 0 :(得分:2)

如果我正确理解了您的问题,则无法返回命名箭头函数,但可以返回命名常规函数并以如下方式递归调用它:

const reducer = k => function recurse(a, item) {
//...
    const s_res = _.split(item, k, 1);
    return recurse(a.withMutations(a => {
        a.push(s_res[0]);
        let a_element = document.createElement('a');
        a_element.setAttribute('href', '#');
        a_element.addEventListener('click', () => display_gen_element(k, obj));
        a.push(a_element);
    }), s_res[1]);
};

P.S。出于可读性考虑,请不要使用一个字母的变量名,除非该变量名令人一目了然,例如for循环中的计数器等。

答案 1 :(得分:0)

如果您的目的是消除自我传递的必要性

...self(self, lst)

您可以通过添加另外1个名为recursor的函数来做到这一点

const map = (mapper = n => n + 1) => (lst = [1, 2, 3]) => {
  const recursor = lst => {
    if (lst.length === 0) return [];
    else return [mapper(...lst.splice(0, 1)), ...recursor(lst)];
  };
  return recursor(lst);
};
const inc = n => n + 1;
const map_inc = map(inc);
console.log(map_inc([1, 2, 3])); // => (produces) [2,3,4]

您根本不需要名为y的类似于y的组合器函数。

recursor的结尾处有mapper