【问题标题】:How to lift and compose functions together?如何一起提升和组合功能?
【发布时间】:2019-10-05 17:03:15
【问题描述】:

我有这个结构中的人员列表:

const people = [
  {name: 'jenny', friends: ['jeff']},
  {name: 'frank', friends: ['jeff', 'ross']},
  {name: 'sarah', friends: []},
  {name: 'jeff', friends: ['jenny', 'frank']},
  {name: 'russ', friends: []},
  {name: 'calvin', friends: []},
  {name: 'ross', friends: ['frank']},
];

我想通过两种方式过滤人:有朋友和没有朋友;此外,我希望Array.filterPredicatelifted,如下所示:

const peopleWithoutFriends = people.filter(withoutFriends);
console.log(peopleWithoutFriends);

const peopleWithFriends = people.filter(withFriends);
console.log(peopleWithFriends);

我可以通过像这样显式编写by 函数来实现这种行为:

const by = x => i => {
  return Boolean(get(i, x));
};
const withFriends = by('friends.length');
const peopleWithFriends = people.filter(withFriends);
console.log(peopleWithFriends);

问题:如果我想要逆向,我需要为peopleWithoutFriends 显式编写一个全新的函数

const notBy = x => i => {
  return !Boolean(get(i, x));
};

const withOutFriends = notBy('friends.length');
const peopleWithoutFriends = people.filter(withOutFriends);

我不想写我的by 函数两次。我宁愿把更小的函数组合在一起。

问题:

我如何编写和使用小函数,例如:flowBooleangetcurrynot 并在列表中为我的 Array.filter 编写 withFriendswithOutFriends 谓词people.

回复:https://repl.it/@matthewharwood/ChiefWelloffPaintprogram

const {flow, get, curry} = require('lodash');

const people = [
  {name: 'jenny', friends: ['jeff']},
  {name: 'frank', friends: ['jeff', 'ross']},
  {name: 'sarah', friends: []},
  {name: 'jeff', friends: ['jenny', 'frank']},
  {name: 'russ', friends: []},
  {name: 'calvin', friends: []},
  {name: 'ross', friends: ['frank']},
];
const not = i => !i;

const withFriends = i => flow(
  Boolean,
  get(i, 'friends.length'), // arity of this is 2 so might be harder to lift, is it possible tho with curry?
); // No idea what i'm doing here.


const peopleWithFriends = people.filter(withFriends);
console.log(peopleWithFriends);

const withoutFriends = flow(not, withFriends);
const peopleWithoutFriends = people.filter(withoutFriends);
console.log(peopleWithoutFriends);

【问题讨论】:

  • 您可能也对lodash/fp 感兴趣

标签: javascript functional-programming lodash ramda.js lifting


【解决方案1】:

由于有/无朋友函数的结果是布尔值,因此您可以否定(或补充)一个结果以获得另一个结果。此外,函数的数量为 1(它们操作的对象)。

Lodash/fp:

const { flow, get, isEmpty, negate } = _;

const people = [
  {name: 'jenny', friends: ['jeff']},
  {name: 'frank', friends: ['jeff', 'ross']},
  {name: 'sarah', friends: []},
  {name: 'jeff', friends: ['jenny', 'frank']},
  {name: 'russ', friends: []},
  {name: 'calvin', friends: []},
  {name: 'ross', friends: ['frank']},
];

const withoutFriends = flow(get('friends'), isEmpty); // create a function that gets the friends array, and check if it is empty
const withFriends = negate(withoutFriends); // negate the result of withoutFriends

const peopleWithFriends = people.filter(withFriends);
console.log(peopleWithFriends);

const peopleWithoutFriends = people.filter(withoutFriends);
console.log(peopleWithoutFriends);
<script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>

拉姆达:

const { pipe, prop, isEmpty, complement } = R;

const people = [
  {name: 'jenny', friends: ['jeff']},
  {name: 'frank', friends: ['jeff', 'ross']},
  {name: 'sarah', friends: []},
  {name: 'jeff', friends: ['jenny', 'frank']},
  {name: 'russ', friends: []},
  {name: 'calvin', friends: []},
  {name: 'ross', friends: ['frank']},
];

const withoutFriends = pipe(prop('friends'), isEmpty); // create a function that gets the friends array, and check if it is empty
const withFriends = complement(withoutFriends); // negate the result of withoutFriends

const peopleWithFriends = people.filter(withFriends);
console.log(peopleWithFriends);

const peopleWithoutFriends = people.filter(withoutFriends);
console.log(peopleWithoutFriends);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>

注意事项:

  1. _.flow()R.pipe 都执行从左到右(从上到下)的序列。 _.compose()R.compose 函数的顺序是相反的。
  2. flow/pipe/compose 中的第一个函数获取传递给组合函数的所有内容。序列中的其他函数总是得到一个参数(前一个函数的结果)/。
  3. Ramda 和 Lodash 都有一个拒绝方法,它与过滤器相反,如果谓词返回true,则删除该项目。例如,R.reject(foo, xs) 等价于 R.filter(R.complement(foo), xs)。 (@ScottSauyet 在此 comment 中注明)

【讨论】:

  • 在函数式编程中,有时术语比实际应用更令人困惑:)
  • flowpipe 都执行从右到左的序列...” - 我想你的意思是 “从左到右” .
  • @user633183 - 确实 :) 已修复。
  • 另请注意,Ramda 的reject 在这里可能很有用。 R.reject(foo, xs) 等价于 R.filter(R.complement(foo), xs)
猜你喜欢
  • 2011-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-25
相关资源
最近更新 更多