部分应用和柯里化
函数的输入来自于参数,其中包含函数定义的形参和实际执行时的实参
通过部分应用延迟实参传入
函数式编程重在声明式和可读性,而且强调每个函数尽量解决一个单一问题。
图片
函数式编程中,我们通常会使用部分应用。
它所做的就是抽象一个 partial 工具,在先预制部分参数的情况下,后续再传入剩余的参数值。如以下代码所示:

var fetchOrder = partial( orderEventHandler, "http://some.api/order" );
var getCurrentOrder = partial( fetchOrder, { order: CURRENT_ORDER_ID } );

...拓展操作符可以在函数调用或数组构造时,将数组表达式或者 string 在语法层面展开。在这里,我们可以用它来处理预置的和后置的实参。而闭包在这里再次发挥了记忆的功能,它会记住前置的参数,并在下一次收到后置的参数时,可以和前面记住的前置参数一起执行。

var partial =
    (fn,...presetArgs) =>
        (...laterArgs) =>
            fn( ...presetArgs, ...laterArgs );

通过柯里化每次传一个参数 延展操作符可以在函数调用链中起到承上启下的作用。
图片
一个普通的函数通常是在调用点执行时传入参数的,而通过部分应用和柯里化,我们做到了可以先传入部分已知参数,再在之后的某个时间传入部分参数,这样从时间和空间上,就将一个函数分开了。
其他好处:
处理未知,让函数从抽象变具体、让具体的函数每次只专心做好一件事、减少参数数量之外,还有一个更抽象的好处,就是体现了函数式底层的声明式思想。
常用的参数处理工具:
在函数式编程中,我们把参数的数量叫做 arity。部分应用可以减少每次函数调用时需要传入的参数,而柯里化更是把函数调用时需要传入的参数数量,降到了 1。它们实际上都起到了控制参数数量的作用。改造接口 unary:一元参数(unary)把一个接收多个参数的函数,变成一个只接收一个参数的函数。

function unary(fn) {
    return function oneArg(arg){
        return fn( arg );
    };
}

示例:

["1","2","3","4","5"].map( unary( parseInt ) ); // [1,2,3,4,5]

改造参数 constant:
函数签名:函数签名一般包含了参数及其类型返回值,还有类型可能引发或传回的异常,以及相关的方法在面向对象中的可用性信息(如关键字 public、static 或 prototype)。
你可以看到在 C 或 C++ 中,会有类似这样的签名

function constant(v) {
    return function value(){
        return v;
    };
}

我们就可以把值包装在 constant 函数里,通过这样的方式,就可以把值作为函数参数传入了。

promise1.then( action1 ).then( constant( 34 ) ).then( action3 );

不做改造 identity一个函数式编程中常用的工具,也就是 identity,它既不改变函数,也不改变参数。它的功能就是输入一个值,返回一个同样的值。

function identity(v) {
    return v;
}

可以作为断言(predicate), 来过滤掉空值。在函数式编程中,断言是一个可以用来做判断条件的函数,在这个例子里,identity 就作为判断一个值是否为空的断言。

var words = "   hello world  ".split( /\s|\b/ );
words; // ['', '', '', 'hello', 'world', '', '']

words.filter( identity ); // ['hello', 'world']

参数的顺序问题
重新排序的方式有很多,可以通过解构(destructure),从数组和对象参数中提取值,对变量进行赋值时重新排序;或通过延展操作符把一个对象中的一组值,“延展”成单独的参数来处理;又或者通过 .toString() 和正则表达式解析函数中的参数做处理。


豪猪
4 声望4 粉丝

undefined