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

JavaScript函数式编程之函数组合函数compose和pipe的实现 #15

Open
zhuanyongxigua opened this issue May 30, 2018 · 0 comments

Comments

@zhuanyongxigua
Copy link
Owner

zhuanyongxigua commented May 30, 2018

函数组合是函数式编程中非常重要的思想,它的实现的思路也没有特别复杂。有两种函数组合的方式,一种是pipe,另一种是compose。前者从左向右组合函数,后者方向相反。
下面就是一个最简单的可以组合两个函数的compose

let compose = (f, g) => (...args) => f(g(...args));

在实际应用中,只能组合两个函数的组合函数显然不能满足要求,我们需要可以组合任意个函数的组合函数。下面提供两种思路。

一种思路

两种方法一种是递归,一种是循环,其实都是一样的。具体的思路就是,先写一个组合可以两个函数的compose2,用compose2先把传进来的末尾的两个函数组合了,返回一个函数func,然后再compose2把func和传进来的下一个函数组合起来,以此类推。

循环的方法

let compose2 = (f, g) => (...args) => f(g(...args));
let compose = (...funcArgs) => (...args) => {
  let funced = funcArgs[funcArgs.length - 1];
  for (let i = funcArgs.length - 2; i >= 0; i--) {
    if (i === 0) {
      return compose2(funcArgs[i], funced)(...args);
    }
    funced = compose2(funcArgs[i], funced);
  }
}

// 与compose组合方向相反的函数组合函数
let pipe = (...funcArgs) => compose(...funcArgs.reverse());

递归的方法

let compose2 = (f, g) => (...args) => f(g(...args));
let compose = (...funcArgs) => (...args) => {
  let [...funcArgsCopy] = funcArgs;
  let callSelf = func => {
    if (funcArgsCopy.length === 0) return func;
    let funced = compose2(funcArgsCopy.pop(), func);
    return callSelf(funced);
  }
  return callSelf(funcArgsCopy.pop())(...args);
}

let pipe = (...funcArgs) => compose(...funcArgs.reverse());

更简单的思路

上面的思路还是有点麻烦,其实不用纠结在组合,直接把前一个函数的处理参数之后的返回值传给下一个函数就可以了。
循环的方法

let compose = (...funcArgs) => (...args) => {
  for (let i = funcArgs.length - 1; i >= 0; i--) {
    args = i === funcArgs.length - 1 ? funcArgs[i](...args) : funcArgs[i](args);
  }
  return args;
}

let pipe = (...funcArgs) => compose(...funcArgs.reverse());

递归的方法

let compose = (...funcArgs) => (...args) => {
  let [...funcArgsCopy] = funcArgs;
  let funced = (...func) => {
    if (funcArgsCopy.length === 0) return func[0];
    func = funcArgsCopy.pop()(...func);
    return funced(func);
  }
  return funced(...args);
}

let pipe = (...funcArgs) => compose(...funcArgs.reverse());

我在github https://github.com/zhuanyongxigua/blog

@zhuanyongxigua zhuanyongxigua changed the title 闲的没事写了两种实现不限参数个数的函数组合函数compose JavaScript函数式编程之函数组合函数compose和pipe的实现 May 31, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant