Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/477.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 用函数式编程方法创建组合函数_Javascript_Functional Programming_Reducers - Fatal编程技术网

Javascript 用函数式编程方法创建组合函数

Javascript 用函数式编程方法创建组合函数,javascript,functional-programming,reducers,Javascript,Functional Programming,Reducers,我试图通过重新创建compose来理解compose是如何工作的。作为其中的一部分,我创建了一个简单的计算器来计算一个值,并根据该值返回利息 本质上,最终目标是创建一个可以执行以下操作的函数。 很好:能够传递多个存款值,并且随着时间的推移可能会计算复利 最好有一些评论,这样我就可以理解函数式编程方法的进展了 (()=>{ // Generic compose function to handle anything const compose = (...fns) =&g

我试图通过重新创建compose来理解compose是如何工作的。作为其中的一部分,我创建了一个简单的计算器来计算一个值,并根据该值返回利息

本质上,最终目标是创建一个可以执行以下操作的函数。

很好:能够传递多个存款值,并且随着时间的推移可能会计算复利

最好有一些评论,这样我就可以理解函数式编程方法的进展了

(()=>{
    // Generic compose function to handle anything
    const compose = (...fns) => (x) => {
        return fns.reduceRight((acc,fn)=>{
            return fn(acc);
        }, x)
    };

    const getInterest = (value) => {
        if (value < 1000) {
            return 1 / 100
        }

        if (value < 10000) {
            return 2 / 100
        }

        return 3 / 100;
    };

    const getDeposit = (value) => {
        return value;
    };

    const calculator = compose(getDeposit, getInterest)

    console.log(calculator(1000)) // Should return value of 1000 * interest rate. I currently get 0.03
})();
(()=>{
//通用的compose函数来处理任何事情
常量组合=(…fns)=>(x)=>{
返回fns.减速器右侧((acc,fn)=>{
返回fn(acc);
},x)
};
const getInterest=(值)=>{
如果(值<1000){
返回1/100
}
如果(值<10000){
返回2/100
}
返回3/100;
};
const getDeposit=(值)=>{
返回值;
};
常量计算器=组合(getDeposit,getInterest)
console.log(calculator(1000))//应该返回1000*利率的值。我当前得到0.03
})();

问题在于,你永远不会将两个值相乘:值和利息

因此,您应该将另一个函数传递到合成中,这将使前面的两个结果相乘

这意味着此函数需要获取2个参数,而其他两个只获取一个参数。通常,函数可能需要任意数量的参数。因此,编写器应该能够向每个函数传递足够的参数。此外,函数还可以返回多个值——以数组的形式。这些值应作为链中下一个函数的参数提供,同时保持所有以前返回的值可用

另一件事是,尽管您已经实现了从右到左执行函数的
compose
,但是您传递的函数序列似乎表明您希望它们从左到右执行,首先是
getDeposit
,然后是
getInterest
,即使在您的情况下它是双向执行的。尽管如此,我还是建议他们改变立场

因此,以下是如何使所有这些工作正常进行:

(()=>{
//通用的compose函数来处理任何事情
常量组合=(…fns)=>(…args)=>{
返回fns.减速器右侧((acc,fn)=>{
//使用到目前为止收集的所有值调用函数
设ret=fn.apply(空,acc);
//如果函数返回一个非数组,则将其转换为具有一个值的数组
如果(!Array.isArray(ret))ret=[ret];
//将返回的值重新排入累加器,以便它们可以
//用作下一个函数调用的参数
acc.unshift(…ret);
返回acc;
},args)[0];//只返回最后插入的值
};
const getInterest=(值)=>{
返回值<1000?0.01
:值<10000?0.02
: 0.03;
};
常数乘法=(a,b)=>a*b;
const getDeposit=(值)=>值;
//请注意,首先执行最右边的函数:
常量计算器=合成(乘法、获取利息、获取存款);
log(calculator(1000))//返回20,即0.02*1000

})();我实际上很喜欢你的简单的compose函数(它只适用于一元函数),我想你现在也可以通过做以下更改来让它工作:

  • getInterest
    重命名为
    …Rate
    ,因为它返回一个值的乘数
  • 添加一个新的
    getInterest
    函数,该函数以货币形式接受“rate getter”和“value”:
    getRate=>x=>getRate(x)*x
  • compose

    我认为
    compose
    通常从右到左(
    f=>g=>x)工作
    =>f(g(x))
    ),管道从左到右工作(
    f=>g=>x=>g(f(x))

(()=>{
//通用的compose函数来处理任何事情
常量组合=(…fns)=>(x)=>{
返回fns.减速器右侧((acc,fn)=>{
返回fn(acc);
},x)
};
const defaultRate=(值)=>{
如果(值<1000){
返回1/100
}
如果(值<10000){
返回2/100
}
返回3/100;
};
const getInterest=getRate=>x=>getRate(x)*x;
const getDeposit=x=>1000;
const calculator=compose(获取利息(默认利率),获取存款);
log(calculator());

})();啊,解决一个部分。。。但是如何使
getInterest
可重用?例如,我想用“利率”代替。但是保持
getInterest
不变,因为它的计算方式不会改变,也不会知道利率?从
getDeposit
getInterestRate
获取值(或任何其他方法)使用这些值计算利息/结果?请参阅更新的答案。它更通用,可以将任意数量的结果从一个函数传递到下一个函数,在
acc
中维护一个值队列。在“compose”的纯解释中,一个函数实际上只是从上一个函数调用中获取结果,而不是其他任何结果。但是,由于您希望有一个返回速率的函数,这样严格的解释将允许链中的下一个函数仅获取速率作为信息,这还不足以进行计算。这就是为什么我建议使用一个更扩展的“compose”(或者实际上是一个“sequence”,因为它从左到右执行函数),它会记住所有以前的函数结果,并将它们全部传递给下一个调用。请参阅我答案的更新。我希望它对你有用。当你从右边归约时,
acc
应该是第二个参数