柯里化

柯里化

高阶函数

在说明柯里化之前,首先需要理解高阶函数的定义

高阶函数是指以函数作为参数的函数,伪代码可以理解为

function higherOrderFunction(fn) {
    console.log(typeof fn) // "function"
    
}

定义

在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。

从定义中我们可以对柯里化的步骤做一个简要的概括:

  1. 存在一个函数currying,接受一个函数source作为参数,并返回一个函数tmpCurrying。
  2. tmpCurrying接收单一参数,并再次返回一个tmpCurrying,直到所有tmpCurrying接收的参数和等于source函数所需的形参数量。
  3. 将tmpCurrying收到的所有单一参数按顺序放入source函数,并执行,以获得结果。

实际应用

使用形式

根据如上定义,可以用如下伪码表示柯里化的使用

  1. 参数分步输入
// 实现参数分步输入
function sum(a,b,c) {
    return [...args].reduce((pre,next) => (pre + next));
}

// 存在一个函数currying

const curriedSum = currying(sum);

curriedSum(1)(2)(3); // 6;
curriedSum(1, 2)(3); // 6;
curriedSum(1, 2, 3); // 6;
  1. 函数抽象,高阶函数封装
// 用于函数抽象,高阶函数封装等
// 存在如下功能函数

function isPhone(number) {
    return /^1[34578]\d{9}$/.test(number);
}

function isMail(mail) {
    return /^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/.test(mail);
}

/*
    可以讲上面两个函数抽象为
    regString.test(targetString);
*/
function check(reg, target) {
    return reg.test(target);
}


/*
    但是每次使用时仍然需要输入正则作为参数,于是考虑利用柯里化的功能,将函数参数拆为两部分,正则 + 校验对象
    假设存在一个柯里化函数currying(fn, reg)
*/



export const checkPhone = currying(check, /^1[34578]\d{9}$/);

export const checkMail = currying(check, /^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/);


/* 
    checkPhone和checkMail此时皆是只需要一个参数targetString的函数
    使用时只需直接使用即可
*/

checkPhone(13111111111); // true;

柯里化实现

想要实现柯里化函数,需要掌握以下知识点

  1. 闭包:内层函数可以访问外层函数的变量
  2. Function.length: 函数的length属性表示其声明时的形参数量
  3. arguments: 类数组arguments表示函数调用时的实参列表(或直接使用参数解构,获取实参数组,推荐此种。原因:arguments只是类数组,没有数组方法,不方便使用,需要用结构或apply等方式将其转化为数组)

实现解析

  1. 利用闭包将每次单独输入的参数存入外层函数currying的数组变量args中。
  2. 校验当前args的长度与被封装函数的形参数量是否相等,不相等则继续返回接受参数的中间函数。
  3. 若相等,则将参数放入源函数并返回执行结果。

实现1---每次只接受一个参数

function currying(src) {
    // 记录源函数的形参长度
    const length = src.length;
    // 参数列表
    const argsPool = [];
    
    return function tmpFn (arg) {
        // 将参数推入参数池
        argsPool.push(arg);
        
        // 长度判断
        if (length > argsPool.length) {
            return tmpFn;
        } else {
            const res = src(...argsPool);
            argsPool = [];
            return res;
        }
    }
}


function sum(a, b, c, d, e, f) {
    return [...arguments].reduce((pre, next) => (pre + next));
}


const _sum = currying(sum);
_sum(1)(2)(3)(4)(5)(6); // 21

实现2:每次接受若干个参数

function currying(src, ...args) {
    // 记录源函数的形参长度
    const length = src.length;
    // 参数列表
    const argsPool = [...args];
    
    return function tmpFn (...args) {
        // 将参数推入参数池
        argsPool.push(...args);
        
        // 长度判断
        if (length > argsPool.length) {
            return tmpFn;
        } else {
            const res = src(...argsPool);
            argsPool = [];
            return res;
        }
    }
}


function sum(a, b, c, d, e, f) {
    return [...arguments].reduce((pre, next) => (pre + next));
}


const _sum = currying(sum);
_sum(1)(2)(3)(4)(5)(6); // 21
_sum(1, 2, 3, 4)(5, 6); // 21

实现3:不规定参数个数,以无参数传入为循环终止标识

function currying(src, ...args) {
    // 参数列表
    let argsPool = [...args];
    
    
    return function tmpFn (...args) {
        if (args.length > 0) {
            argsPool.push(...args);
            return tmpFn;
        } else {
            const res = src(...argsPool);
            argsPool = [];
            return res;
        }
    }
}


function sum(...args) {
    return args.reduce((pre, next) => (pre + next));
}


const _sum = currying(sum);

_sum(1,2,3)(4,5)(); // 15
_sum(1,2)();        // 3
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
柯里化是一种函数式编程的概念,它指的是将一个接受多个参数的函数转化为一系列只接受单个参数的函数的过程。在Python中,可以通过使用闭包或者装饰器来实现柯里化。 闭包是指在一个内部函数中引用了外部函数的变量,并且该内部函数可以在外部函数调用结束后继续访问这些变量。通过使用闭包,我们可以实现柯里化。下面是一个使用闭包实现柯里化的示例: ```python def add(x): def inner(y): return x + y return inner add_5 = add(5) print(add_5(3)) # 输出 8 ``` 在上面的例子中,`add` 函数接受一个参数 `x`,并返回一个内部函数 `inner`。内部函数 `inner` 接受参数 `y`,并返回 `x + y` 的结果。通过调用 `add(5)`,我们得到了一个新的函数 `add_5`,它只需要一个参数 `y`,并且会将 `x` 固定为 5。这样,我们就实现了柯里化。 除了使用闭包,还可以使用装饰器来实现柯里化。下面是一个使用装饰器实现柯里化的示例: ```python def curry(func): def inner(*args): if len(args) >= func.__code__.co_argcount: return func(*args) return inner return inner @curry def add(x, y): return x + y add_5 = add(5) print(add_5(3)) # 输出 8 ``` 在上面的例子中,我们定义了一个装饰器 `curry`,它接受一个函数 `func` 作为参数,并返回一个新的函数 `inner`。新的函数 `inner` 接受任意数量的参数 `args`,如果参数个数足够,则调用原始函数 `func` 并返回结果;否则,返回自身。通过在 `add` 函数上应用装饰器 `@curry`,我们实现了柯里化
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值