Piping Hot Merges

Understanding argument order with pipe and merge in Lodash FP
13 June 2024
Web development

Getting it wrong

When using pipe and merge, the order of args is a little confusing. We want objInitial <- objA <- objB <- objC

import { merge, pipe } from 'lodash/fp'

// wrong but intuitive:
pipe(
  merge(objA),
  merge(objB),
  merge(objC),
)(objInitial)

Given the above example, it initially looks like objInitial will be merged into objA, and then objB will be merged onto that result, then objC into that result and so on:

// wrong but intuitive:
merge(merge(merge(objA, objInitial), objB), objC)

But the order is actually reversed due to the previous result in pipe becoming the last arg in the next fn call. It actually becomes objC <- objB <- objA <- objInitial:

merge(objC, merge(objB, merge(objA, objInitial)))

Getting it right

Since the second arg of merge overwrites the first arg, we need to reverse the order:

import { merge, pipe } from 'lodash/fp'

// correct but unintuitive
pipe(
  merge(objB),
  merge(objA),
  merge(objInitial),
)(objC)

Which will give us the correct objInitial <- objA <- objB <- objC:

merge(objInitial, merge(objA, merge(objB, objC)))