链接和函数组合

Chaining and Function Composition

这是我试图理解的一段代码:

const seq2 = (f1, f2) => {
 return (...args) => {

  return f2( f1( ...args) );
 }
}



const seq = ( f1, ...fRest) =>
 fRest.reduce( seq2, f1 );

const elevator = {
 floor: 5
};

const up = elevator => {
 return {
  floor: elevator.floor + 1
 }
};

const down = elevator => {
 return {
  floor: elevator.floor - 1
 }
};


const move = seq( up, up, down, up);
const newElevator = move( elevator );



console.log( newElevator.floor ) // shows 7

这是js函数式编程课程中的一个例子。我想弄清楚我是否可以简化 seq 函数,所以它看起来像这样

const seq = ( ...fRest) => fRest.reduce( seq2 );

????

为什么我必须将 f1 作为第一个参数传递,然后将其作为 initialValue 进一步传递给 reduce 方法?当我不在 reduce 方法中指定 initialValue 时,它不会默认将第一个数组元素 - accumulator - 视为 initialValue 吗?如果有人能向我解释该代码中发生了什么,我将不胜感激:)

seq() 会尝试减少没有累加器的空数组,这是一个错误——并不是说 f1 按照作者在这里写的方式解决了这个问题。

initialValue – Value to use as the first argument to the first call of the callback. If no initial value is supplied, the first element in the array will be used. Calling reduce() on an empty array without an initial value is an error – source MDN: Array.prototype.reduce

seq() 用于构建空序列

时,seq 的更健壮的实现不会导致错误

const identity = x =>
  x

const seq2 = (f, g) =>
  (...args) => f (g (...args))

const seq = (f = identity, ...rest) =>
  rest.reduce (seq2, f)

const up = elevator =>
  ({ floor: elevator.floor + 1 })
  
const down = elevator =>
  ({ floor: elevator.floor - 1 })

console.log
 ( seq (up, up, down, up) ({ floor: 3 }) // { floor: 5 }
 , seq () ({ floor: 3 })                 // { floor: 3 }
 )

seq 的简化版本,通过禁止组合可变函数来促进更好的功能卫生

const identity = x =>
  x

const seq = (f = identity, ...rest) =>
  f === identity
    ? f
    : x => seq (...rest) (f (x))

const up = elevator =>
  ({ floor: elevator.floor + 1 })
  
const down = elevator =>
  ({ floor: elevator.floor - 1 })

console.log
 ( seq (up, up, down, up) ({ floor: 3 }) // { floor: 5 }
 , seq () ({ floor: 3 })                 // { floor: 3 }
 )