4

I'm trying to make middleware function lets call it debug, which should take some parameters, log them and pass to the next function:

const debug = (...args) => {
 console.log(...args)
 return args // will return array, not argument type variable
}

const compose = (...fns) => (...arg) => (
  fns.slice().reverse().reduce(
    (acc, fn) => !acc ? fn(...arg) : fn(acc), null
  )
)

const f = x => x * x

const g = (a, b) => a + b

const makeMagic = compose(
  f,
  g,
  debug
)

makeMagic(1, 2)

If I remove debug from composition everything works as expected, as soon as I place it at end, it breaks. Because it takes arguments but returns array.

I tried to rewrite debug this way:

function debug() {
  console.info(arguments)
  return arguments
}

But no way it fails.

sultan
  • 4,543
  • 2
  • 24
  • 32

1 Answers1

3

A function always has only a single result value. You can't write a function that accepts multiple arguments and "returns" multiple values without some kind of container around them (like an array), it's just not a feature JavaScript has (nor do most other programming languages).

You can make debug a pure pass-through for a single argument, but not multiple. So for instance, you could make this work:

const result = debug(makeMagic(1, 2))

...where result would be the value makeMagic returned (after debug logs it), but you can't include it in the composed makeMagic the way you're trying to.

To have debug (or any other function) in the middle of a chain with your compose, you'd have to use a convention with it and all composeable functions about how they return multiple values, probably by having them all return an array. That also helps with the fact taht right now, your compose function has what I assume is a bug: It uses ...args any time a previous function returned a falsy value (0, "", NaN, null, undefined, or false), where I'm fairly sure you meant to do that only on the first call.

Here's a version of compose that expects composable functions, which are functions that return an array of their results:

const debug = (...args) => {
    console.log(...args);
    return args;
};

const compose = (...fns) => (...args) => (
    fns.slice().reverse().reduce(
        (acc, fn) => fn(...(acc || args)),
        null
    )
);

const f = x => [x * x];

const g = (a, b) => [a + b];

const makeMagic = compose(
    f,
    g,
    debug
);

const result = makeMagic(1, 2);
console.log(result);
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875