Here is a piece of code I am trying to understand:
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
this is an example from js functional programming course. And I am trying to figure out if I could simplify seq function so it would look like this
const seq = ( ...fRest) =>
fRest.reduce( seq2 );
????
Is there any specific reason why I have to pass f1
as a first argument and then pass it further to the reduce method as an initialValue
?? When I won't specify the initialValue
in the reduce method wouldn't it treat the first array element - accumulator
- as an initialValue
by default? I will much appreciate if someone could explain to me what is going on in that code :)
seq()
would attempt to reduce an empty array without an accumulator, which is an error – not that f1
fixes this the way the author has it written here.
initialValue
– Value to use as the first argument to the first call of thecallback
. If no initial value is supplied, the first element in the array will be used. Callingreduce()
on an empty array without an initial value is an error – source MDN: Array.prototype.reduce
A more robust implementation of seq
will not cause an error when seq()
is used to build an empty sequence
const identity = x =>
x
const seq2 = (f, g) =>
(...args) => f (g (...args))
const seq = (...fs) =>
fs.reduce (seq2, identity)
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 }
)
A simplified version of seq
that promotes better functional hygiene by disallowing composition of variadic functions
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 }
)