跳到主要内容

函数组合

函数组合(Function Composition)是将多个函数组合成一个新函数的过程,是函数式编程的核心技术之一。

什么是函数组合?

函数组合是将一个函数的输出作为另一个函数的输入,将多个简单函数组合成复杂函数。

// f(g(x)) 表示先执行 g,再执行 f
const compose = (f, g) => x => f(g(x));

// 示例
const add1 = x => x + 1;
const multiply2 = x => x * 2;

const add1ThenMultiply2 = compose(multiply2, add1);
add1ThenMultiply2(5); // (5 + 1) * 2 = 12

组合与管道

compose(从右到左)

const compose = (...fns) => x => 
fns.reduceRight((v, f) => f(v), x);

const transform = compose(
x => x.toUpperCase(),
x => x.trim(),
x => x.replace(/\s+/g, ' ')
);

transform(' hello world '); // 'HELLO WORLD'

pipe(从左到右)

const pipe = (...fns) => x => 
fns.reduce((v, f) => f(v), x);

const transform = pipe(
x => x.replace(/\s+/g, ' '),
x => x.trim(),
x => x.toUpperCase()
);

transform(' hello world '); // 'HELLO WORLD'

实际应用示例

数据处理管道

const users = [
{ name: 'John', age: 25, active: true },
{ name: 'Jane', age: 30, active: false },
{ name: 'Bob', age: 35, active: true }
];

const getActiveUsers = users => users.filter(u => u.active);
const getNames = users => users.map(u => u.name);
const sortNames = names => names.sort();
const joinNames = names => names.join(', ');

const processUsers = pipe(
getActiveUsers,
getNames,
sortNames,
joinNames
);

processUsers(users); // 'Bob, John'

验证管道

const isNotEmpty = x => x.length > 0;
const isEmail = x => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(x);
const isLongEnough = x => x.length >= 8;

const validate = pipe(
isNotEmpty,
isEmail,
isLongEnough
);

组合的优势

  1. 代码复用:小函数可以在多处组合使用
  2. 可读性:声明式代码更易理解
  3. 可测试性:纯函数易于单元测试
  4. 可维护性:修改单个函数不影响其他部分

组合的最佳实践

  1. 单一职责:每个函数只做一件事
  2. 纯函数:确保组合函数没有副作用
  3. 类型一致:确保函数输入输出类型匹配
  4. 适度组合:避免过长的组合链

Ramda 中的组合

const R = require('ramda');

const transform = R.pipe(
R.replace(/\s+/g, ' '),
R.trim,
R.toUpper
);

// 或使用 compose(从右到左)
const transform2 = R.compose(
R.toUpper,
R.trim,
R.replace(/\s+/g, ' ')
);