5

I'm trying to refactor this function to be pointfree.

function siblings(me) {
  return R.pipe(family, R.reject(equalsMe(me)))(me);
}

I'd like to pass me to a function down the pipe along with the value that family returns.

Tried a few things with R.useWith or R.converge with R.identity or R.__ (not even sure if I should be using that) but found nothing to work.

customcommander
  • 17,580
  • 5
  • 58
  • 84
AKG
  • 2,936
  • 5
  • 27
  • 36

3 Answers3

7

I'd also suggest using R.converge and swapping R.reject(equalsMe(me)) with R.without(me)

const withFamily = R.always(['fratello', 'sorella', 'io']);

const siblingsOf = R.converge(R.without, [
  R.identity,
  withFamily,
]);

console.log(
  siblingsOf('io'),
);

console.log(
  siblingsOf('sorella'),
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.js" integrity="sha512-3sdB9mAxNh2MIo6YkY05uY1qjkywAlDfCf5u1cSotv6k9CZUSyHVf4BJSpTYgla+YHLaHG8LUpqV7MHctlYzlw==" crossorigin="anonymous"></script>
Hitmands
  • 13,491
  • 4
  • 34
  • 69
6

If you're using R.without (as suggested in Hitmands answer), you can use R.chain with a flipped R.without:

chain(flip(without), withFamily);

Because chain(f, g)(x) is equivalent to f(g(x), x):

chain(flip(without), withFamily)(me)

equals to:

flippedWithout(withFamily(me), me)

Example:

const { always, chain, flip, without } = R;

const withFamily = always(['fratello', 'sorella', 'io']);

const siblingsOf = chain(flip(without), withFamily);

console.log(
  siblingsOf('io'),
);

console.log(
  siblingsOf('sorella'),
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.js" integrity="sha512-3sdB9mAxNh2MIo6YkY05uY1qjkywAlDfCf5u1cSotv6k9CZUSyHVf4BJSpTYgla+YHLaHG8LUpqV7MHctlYzlw==" crossorigin="anonymous"></script>
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
6

If I understand correctly family is a function that takes a person and returns a list of family members (including that person) e.g.

family(2);
//=> [1, 2, 3]

Then you want to create a function siblings which takes a person and returns only their siblings e.g.

siblings(2);
//=> [1, 3]

Personally I think your function would read slightly better if it was written this way:

const siblings = me => reject(equals(me), family(me));

siblings(2);
//=> [1, 3]

If you really wanted a pointfree version of it, you could use converge but I really don't think it is any better:

const siblings = converge(reject, [unary(equals), family]);
customcommander
  • 17,580
  • 5
  • 58
  • 84
  • Thanks! I was struggling to understand `unary` and `converge` but I think I do now! – AKG Apr 22 '21 at 15:42
  • I like your version with the single `me` parameter. But for point-free, I would prefer `lift` to `converge` wherever it will work, as it does here. So `const siblings = lift (reject) (unary (equals), family)`. If this didn't need `unary`, I'd actually be pretty happy with it. – Scott Sauyet Apr 23 '21 at 13:02