面试官:请你写一个add函数并尝试将它柯里化

562 阅读3分钟

柯里化

它是一个函数式编程的概念,它指的是将一个接受多个参数的函数转换为一系列只接受一个参数的函数。换句话说,柯里化将一个多参数函数转换为一系列嵌套的一元函数(每个函数只接受一个参数)。假设有一个函数 f(a, b, c),柯里化后,它会被转换为 f(a)(b)(c)。

为什么要柯里化

提升函数的可重用性和模块化

  • 柯里化可以将一个多参数函数拆分成多个单参数函数,从而提高函数的复用性。例如,可以创建一个部分应用的函数,再次使用时无需提供所有参数。

便于函数组合

  • 在函数式编程中,函数组合是一种常见的操作。柯里化使得函数组合更简单,因为每个函数只需要一个参数。

简化代码结构

  • 柯里化可以使代码看起来更加简洁和清晰,尤其是在处理需要多次传递相同参数的情况时。通过柯里化,可以将固定的参数提前传递,从而减少重复代码。

延迟计算

  • 柯里化允许你创建一个部分应用的函数,等到需要时再提供剩余的参数。这种延迟计算的能力在某些场景下非常有用,例如在处理复杂的逻辑或优化性能时。

add函数的柯里化

假如面试官叫你写一个add函数出来,实现两个数字的相加,相信你很快就能写出如下代码

 function add(a,b){
    if(arguments.length<2){
        console.log('参数长度不够');
    }
    if(typeof a !=='number'||typeof b !=='number'){
        console.log('参数类型不对');
    }
    return a+b
 }

面试官继续提出需求,请你再实现一个能够延迟计算的add函数,也就是将add函数柯里化。这个时候我们就应该想到闭包的思想,函数里面返回一个函数体,这样就能实现一个简单的柯里化函数了。

function add(num1){
    return function(num2){
        return num1+num2
    }
}
const add5 = add(5);
console.log(add5(3)); // 8

这种方式使得你可以创建一个固定参数的函数(例如 add5),然后在不同场合使用,避免了重复传递相同的参数。

面试官继续提出请你实现一个参数不定的柯里化add函数,这里就涉及到参数收集的问题了。在es5中一般是使用argument来获取参数,在es6中我们使用...来获取,小tips,在使用 es6 的语法时,箭头函数里面没有argument。

let curry = (fn,...args) => {
    // console.log(fn.length,args.length);
    return args.length>=fn.length?fn(...args):(..._args)=>curry(fn,...args,..._args)
}
function add(n1, n2, n3, n4) {
    return n1 + n2 + n3 + n4
}
console.log(curry(add, 1)(2,3,4)); 

curry 函数会在参数数量足够时正确返回 fn 函数的调用结果。否则,它会返回一个接受更多参数的新函数。

使用第三方库柯里化

许多现代编程语言和库都提供了柯里化的支持,比如Ramda.js(JavaScript中的函数式编程库)。以下是如何使用Ramda.js进行柯里化的示例:

const R = require('ramda');
const add = (x, y) => x + y;
const curriedAdd = R.curry(add);
console.log(curriedAdd(2)(3)); // 输出:5

总结

柯里化是一种强大的编程技术,通过将多参数函数转化为一系列一参数函数,可以提升代码的重用性、可读性和灵活性。不同语言和库提供了不同的实现方式,开发者可以根据需要选择合适的方法来应用柯里化。