首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >递归函数的高阶函数?

递归函数的高阶函数?
EN

Stack Overflow用户
提问于 2014-01-05 21:10:57
回答 3查看 1.5K关注 0票数 19

有没有办法通过高阶函数“包装”递归函数,这样递归调用也会被包装?(例如,在每次调用时记录函数的参数。)

例如,假设我们有一个名为sum()的函数,它通过将头部与尾部的和相加来返回数字列表的和:

代码语言:javascript
运行
复制
function sum(a) {
    if (a.length === 0) {
        return 0;
    } else {
        return a[0] + sum(a.slice(1));
    }
}

有没有办法编写一个高阶函数logging(),它接受sum()函数作为输入,并返回一个函数,该函数在每次递归调用时将参数输出到sum()

以下内容不起作用:

代码语言:javascript
运行
复制
function logging(fn) {
    return function(a) {
        console.log(a);
        return fn(a);
    }
}

sum2 = logging(sum);
sum2([1, 2, 3]);

实际输出:

代码语言:javascript
运行
复制
[1, 2, 3]
-> 6

预期输出:

代码语言:javascript
运行
复制
[1, 2, 3]
[2, 3]
[3]
[]
-> 6

如果重写sum(),以便它可以与Y组合器样式的“递归”一起使用,这是可能的吗?

代码语言:javascript
运行
复制
function sum_core(g) {
    return function (a) {
        if (a.length === 0) {
            return 0;
        } else {
            return a[0] + g(a.slice(1));
        }
    };
}

sum = Y(sum_core);
sum([1, 2, 3]);
// -> 6
EN

回答 3

Stack Overflow用户

发布于 2014-01-05 22:04:20

我知道这是一种不能回答的问题,但是如果你使用对象和动态调度的方法,你想要做的事情要容易得多。本质上,我们将"rec“存储在一个可变的单元格中,而不是传递它。

它类似于sum = logging(sum) (而不是sum2 =),但更惯用,并且不会硬编码我们所调度的可变引用的名称。

代码语言:javascript
运行
复制
var obj = {
  sum : function(a){
    if (a.length === 0) {
      return 0;
    } else {
      return a[0] + this.sum(a.slice(1)); // <-- dispatch on `this`
    }
  }
}

function add_logging(obj, funcname){
   var oldf = obj[funcname];
   obj[funcname] = function(/**/){
     console.log(arguments);
     return oldf.apply(this, arguments);
   }
}

add_logging(obj, 'sum');
票数 6
EN

Stack Overflow用户

发布于 2014-01-05 22:32:52

如果不修改函数,这在JavaScript中是不可能的。如果你不想要手工工作,你最好的选择是:

代码语言:javascript
运行
复制
function logged(func){
    return eval("("+func.toString().replace(/function(.*){(.*)/g,"function$1{console.log(arguments);$2")+")");
};

然后你可以像这样使用它:

代码语言:javascript
运行
复制
function sum(a) {
   if (a.length === 0) {
        return 0;
    } else {
        return a[0] + sum(a.slice(1));
    }
}

console.log(logged(sum)([1,2,3,4]));

以下哪项输出:

代码语言:javascript
运行
复制
{ '0': [ 1, 2, 3, 4 ] }
{ '0': [ 2, 3, 4 ] }
{ '0': [ 3, 4 ] }
{ '0': [ 4 ] }
{ '0': [] }
10

logged本身非常慢,因为它(使用eval)重新编译函数,但生成的函数与您手动定义的函数一样快。所以,每个函数只需使用一次logged就可以了。

票数 1
EN

Stack Overflow用户

发布于 2014-01-05 21:14:50

作用域问题。尝试执行以下操作:

代码语言:javascript
运行
复制
function logging(fn) {
    var _fn = fn; // local cached copy
    return function(a) {
        console.log(a);
        return _fn(a);
    }
}
票数 -2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20933928

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档