Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

currying #45

Open
bibi7 opened this issue Nov 5, 2019 · 0 comments
Open

currying #45

bibi7 opened this issue Nov 5, 2019 · 0 comments

Comments

@bibi7
Copy link
Owner

bibi7 commented Nov 5, 2019

函数柯里化又叫部分求值,维基百科中对柯里化 (Currying) 的定义为:

在数学和计算机科学中,柯里化是一种将使用多个参数的函数转换成一系列使用一个参数的函数,并且返回接受余下的参数而且返回结果的新函数的技术。

简单来说,柯里化其实就是一个参数收集的过程,将每一次传入的参数收集起来,然后在最里层再进行处理。

所以一个合格的柯里化函数需要这么几点:

  1. 当参数未收集完毕的时候继续收集参数
  2. 当参数收集完毕后调用方法
const curring = (fn) => {
  const args = []
  return function InnerFn(...rest) {
    if (rest.length === 0) {
      return fn(...args)
    }
    args.push(...rest)
    return InnerFn
  }
}

const add = (...result) => result.reduce((a, b) => a + b)
const sum = curring(add)
sum(1)
sum(2)
sum(3)(4)
sum(5,6)(7)
sum() //28

其实上文所实现的功能就类似于延迟计算,但是有个缺点:

  1. 最后需要多调用一次,也就是类似于sum(1, 2, 3)(4, 5)(6)()

另一种更通用的柯里化:

const currying = (fn) => {
  return inner => (...args) => 
    args.length >= fn.length
      ? fn(...args)
      : (...arg) => inner(...args, ...arg)
}

const fn = currying(function(a, b, c) {
    console.log([a, b, c]);
});

fn("a", "b", "c") // ["a", "b", "c"]
fn("a", "b")("c") // ["a", "b", "c"]
fn("a")("b")("c") // ["a", "b", "c"]
fn("a")("b", "c") // ["a", "b", "c"]

fnn('1',)
//(...arg) => inner(...args, ...arg)
fnn('1','2')
//(...arg) => inner(...args, ...arg)
fnn('1','2')(3)
//["1", "2", 3]

这样我们就实现了一个通用柯里化,实现原理就是「用闭包把传入参数保存起来,当传入参数的数量足够执行函数时,就开始执行函数」。比刚才的延迟计算类型的柯里化更完善一点。

但是我一直很疑惑一点,后者其实会被初始函数的形参个数限定死,万一碰到初始函数形参个数不定的呢?(:з」∠)

@bibi7 bibi7 changed the title curring currying Nov 5, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant