Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

120
Views
Apply callback to 2 arbitrary length arrays using functional programming in JavaScript

Given that these function declarations exist within scope:

function compose() {
  var funcs = arguments;

  return function() {
    var args, i;

    args = arguments;

    for (i = funcs.length - 1; i >= 0; i--) {
      args = [funcs[i].apply(null, args)];
    }

    return args[0];
  };
}

function id(x) {
  return x;
}

function partial(targetfn) {
  var arity = targetfn.length;

  return function fn() {
    if (arguments.length < arity) {
      return Function.prototype.bind.apply(fn, [null].concat(
        Array.prototype.slice.call(arguments)
      ));
    } else {
      return targetfn.apply(null, arguments);
    }
  }
}

Having this callback function as an example:

function cb(x, y) {
  console.log(x);
  console.log(y);
}

Is it possible using FP techniques (such as argument binding, composition and partial application) to apply the callback function to 2 arrays of arbitrary length? E.g.: ["foo", "bar", "baz", "quux"] and [12, 42]? The expected output in this case would be:

foo
12
foo
42
bar
12
bar
42
baz
12
...and so on

Since Array.prototype.forEach and Array.prototype.map pass 3 arguments to the callback function, it's at least possible to iterate over a single array using function composition as follows:

["foo", "bar", "baz", "quux"].forEach(compose(cb, id))

It's also possible to map an array into partially applied functions like so:

[12, 42].map(compose(partial(cb), id))

I've been looking into using Function.prototype.apply, Function.prototype.bind and Function.prototype.call, combining them with Array.prototype.forEach and Array.prototype.map, so far without success. I'm trying hard not to introduce more function declarations / expressions.

Update

Thanks to Mulan, the problem can be solved by splitting it into the part that computes the cartesian product of lists and applying the resulting list to a given function.

function product() {
  var args = [].slice.call(arguments);

  return args.reduce(function(prev, cur) {
    var ret = [];

    prev.forEach(function(x) {
      cur.forEach(function(y) {
        ret.push(x.concat(y));
      });
    });

    return ret;
  }, args.shift().map(function(val) {
    return [val];
  }));
}

product(
  ["foo", "bar", "baz", "quux"],
  [12, 42]
).forEach(Function.prototype.apply.bind(cb, null));
about 4 years ago ยท Juan Pablo Isaza
1 answers
Answer question

0

I think you might be making more work for yourself by forcing compose and partial where they're not particularly useful. It seems like you're looking to compute a product of input arrays. The result is an array of products, each of which contains a unique grouping of elements taken from the input arrays -

function product(a, ...more) {
  if (more.length == 0)
    return a.map(v => [v])
  else 
    return a.flatMap(v => product(...more).map(p => [v, ...p]))
}

function cb(x,y) {
  console.log(x, y)
}

product(["foo", "bar", "baz", "quux"], [12, 42])
  .forEach(p => cb(...p))
.as-console-wrapper { min-height: 100%; top: 0; }

If you really want to use partial, you can accept a callback cb as the first argument, and then all arrays to multiply thereafter. Each step in product applies one argument to cb. The result is an array of products where each product is an array of partially applied functions, which can be executed by calling cb() -

function partial(f, ...x) {
  return (...y) => f(...x, ...y)
}

function product(cb, a, ...more) {
  if (more.length == 0)
    return a.map(v => partial(cb, v))
  else
    return a.flatMap(v => product(partial(cb, v), ...more))
}

const cb = partial(console.log, "i would like")

const res = product(cb,
  ["๐Ÿ”", "๐ŸŒฎ", "๐Ÿฅช"],
  ["๐ŸŸ", "๐Ÿฅจ"],
  ["๐Ÿฅค", "โ˜•๏ธ"]
 )

res.forEach(cb => cb())
.as-console-wrapper { min-height: 100%; top: 0; }

about 4 years ago ยท Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
ยฉ 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!