Jan Turoň
Jan Turoň

Reputation: 32912

Can ES6 natively encode permutations over Set in functional paradigm?

I would like to create permutations over Set(0..n) in Javascript.

I am struggling with Array methods: some of them like map return a new array that could be further modified, others like forEach does not. To encode permutations, I could do it only with enhancing Array prototype:

Object.defineProperty(Array.prototype, "chain", {
  value: function(method, arg) {
    this[method].call(this, arg);
    return this;
  }
});

Object.defineProperty(Array.prototype, "value", {
  value: value => value // to value value ;-)
});

Only then I was able to encode permutations:

let perm = (n) =>
  n==0 ? [[0]] :
  perm(n-1).reduce((acc, cur) =>
    cur.chain("forEach", (_, i) =>
      acc.chain("push", [...cur.slice(0,i), n, ...cur.slice(i)])
    ).value(acc).chain("push", [...cur,n])
  ,[])

Test:

console.log(perm(2));

So is it feasible in ES6 (without adding to Array prototype) to encode permutations over Set (or any Array-like object) in pure functional way?

I don't want to rape Javascript (like jQuery did back then) to force it some non-native paradigm, but I'd like to fully understand its potential on the functional field.

Upvotes: 1

Views: 78

Answers (1)

Bergi
Bergi

Reputation: 664548

No ES6 needed at all. You should not use forEach or push if you want to program in a functional style - and hiding them in a chain method so that you can write expressions with useful return values doesn't help.

Instead, all you want are map and concat:

let perm = (n) =>
  n==0 ? [[0]] :
  perm(n-1).reduce((acc, cur) =>
    acc.concat(cur.map((_, i) =>
      [...cur.slice(0,i), n, ...cur.slice(i)]
    ), [[...cur,n]])
  , [])

Of course you could also replace the concat call by array spread syntax if you're inclined.

Upvotes: 3

Related Questions