-
Notifications
You must be signed in to change notification settings - Fork 2
Open
Description
如果没有接受函数式的一整套理论,就没有必要用柯里化
柯里化 Currying:让所有函数只接受一个参数
有什么意义?
我们把一个只接受一个参数的函数叫作「单参数函数」,基于这种函数,已经衍生出非常多的理论知识,而且是关于数学方面的,跟编程关系不大
如 λ演算 —— lambda演算
假设一个函数只支持一个参数
那么支持接受两个参数呢?
- 使用对象
- 使用闭包
一般来说,在函数式编程中,不使用对象,而是使用闭包,因为 —— 对象是穷人的闭包
如果不理解上面这句话,可以看下我写过的一篇博客对象是穷人的闭包,闭包是穷人的对象
我们有闭包了,就不需要使用对象
使用对象
const add = ({a, b}) => a + b
add({a: 1, b: 2})上面这种方式在函数式编程中,特别的傻
使用闭包
const add = a => b => a + b
add(1)(2)如果没见过上面这种写法,是不是看不太习惯?或者会疑问:闭包在哪里呢?
请继续往下看:
// 以上的代码,基本等价与下面的代码
add = function(a) {
return function(b) {
return a + b // 这个 a 就是和这个函数形成了闭包
}
}
add(1)(2)但是如果只写过 JS 的人,会感觉有点不方便对不对?
没错,如果没有接受过函数式的一整套理论,你会觉得这就是在耍花招,没什么用
但是你如果接受过一系列函数式的东西,你就会觉得柯里化是非常重要的部分,如果没学过,那就没必要用柯里化
柯里化一个函数
初级
请把三参数函数 add(1,2,3) 变成 curriedAdd(1)(2)(3) 形式:
const curriedAdd =
a =>
b =>
c =>
add(a, b, c)完毕,非常的简单。
升级
假设:
- addTwo 接受两个参数
- addThree 接受三个参数
- addFour 接受四个参数
- 如何写出一个
currify函数,使得他们分别接受 2、3、4 次参数,如:currify(addTow)(1)(2) // 3currify(addThree)(1)(2)(3) // 6currify(addFour)(1)(2)(3)(4) // 10
也就是说,currify 函数能将任意接受固定个参数的函数,变成单一参数的函数
const currify = (fn, params = []) => {
return (arg) => {
const newParams = params.concat(arg)
if(newParams.length === fn.length) {
return fn(...newParams)
} else {
return currify(fn, newParams)
}
}
}
const addTwo = (a, b) => a + b再升级
我想支持 currify(addFour)(1)(2,3)(4) // 10
那么需要这么改写
const currify = (fn, params = []) => {
- return (arg) => {
+ return (...args) => {
- const newParams = params.concat(arg)
- if(newParams.length === fn.length) {
+ if(params.length + args.length === fn.length) {
- return fn(...newParams)
+ return fn(...params, ...args)
} else {
- return currify(fn, newParams)
+ return currify(fn, [...params, ...args])
}
}
}最终简化
const currify = (fn, params = []) =>
(...args) =>
params.length + args.length === fn.length
? fn(...params, ...args)
: currify(fn, [...params, ...args])这样,是不是对「柯里化函数」有一点点理解了呢?
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels