JavaScript回调函数与函数式编程

14

"函数式编程仅描述对程序输入执行的操作,而不使用临时变量存储中间结果。"

问题在于如何应用函数式编程并使用利用回调的异步模块。 有些情况下,您希望回调访问一个由调用异步参考的函数引入的变量,但回调的签名已经定义。

例如:

function printSum(file,a){
     //var fs =....
     var c = a+b;
     fs.readFile(file,function cb(err,result){
          print(a+result);///but wait, I can't access a......
     });
}

当然我可以访问a,但这将违背纯函数式编程范式。


2
你可以在函数中访问 a。它被绑定在一个 闭包 中。 - hvgotcodes
3
"函数式编程的那个定义有问题,你从哪里得到的?在函数式编程中,中间结果没有任何问题。" - Jacob
1
定义:http://www.ibm.com/developerworks/library/wa-javascript/index.html#functional - DuduAlul
1
我正在尝试理解函数式编程人员如何克服这些“问题”.. - DuduAlul
JavaScript 从什么时候开始成为“纯函数式”语言的? - Zirak
显示剩余3条评论
3个回答

10
fs.readFile(file, (function cb(err,result){
    print(this.a+result);
}).bind({a: a});

如果必须这样做,只需将带有变量和范围的context注入函数中即可。

因为您抱怨API。

fs.readFile(file, (function cb(a, err,result){
    print(a+result);
}).bind(null, a);

这被称为柯里化。它更加面向函数式编程。


@MrOhad 这是将状态注入回调函数的另一种方式。要么沿着作用域链向上走,要么将数据注入上下文中。实际上还有另一种选择。我添加了柯里化示例,这可能更好。 - Raynos

1

我认为问题在于你误解了他们对中间值的使用的含义(或者他们曲解了它,我没有读过链接)。请考虑,在函数式语言中,变量是某个东西的“定义”,而该定义不能更改。在函数式编程中,使用名称表示值/公式是完全可以接受的,只要它们不改变。

function calculate(a,b,c) {
    // here we define an name to (a+b) so that we can use it later
    // there's nothing wrong with this "functionally", since we don't 
    // change it's definition later
    d = a + b;
    return c * d;
}

另一方面,从功能上讲,以下内容是不可行的。
function sum(listofvalues) {
    sum = 0;
    foreach value in listofvalues
        // this is bad, since we're re-defining "sum"
        sum += value;
    return sum
}

对于你的代码来说,更接近的是…考虑一个函数调用map,它接受一组事物和一个要应用于事物的函数,并返回一组新的事物。完全可以这样说:

function add_value(amount) {
    amount_to_incr = amount * 2;
    return function(amount, value) {
        // 这里我们使用了提供给我们的“amount”值
        // 返回的函数将始终针对相同的输入返回相同的值...它是“引用透明”的
        // 并且它使用“intermediate”值amount_to_incr...但是,由于
        //该值不会改变,所以没问题
        return amount_to_incr + value;
    }
}
map [1,2,3] add_value(2) ;// -> [3,4,5]

2
考虑到许多负面投票,我希望能收到关于它们产生的原因的评论。了解自己的错误并纠正它们是一件好事。 - RHSeeger

0
function printSum(file, a) {
     //var fs =....
     var c = a + b;
     fs.readFile(file, function cb(err, result, aa = a) {
          print(aa + result);
     });
}

现在,使用默认参数,可以将a传递到回调函数中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接