Рамда: где-нибудь? - PullRequest
       16

Рамда: где-нибудь?

2 голосов
/ 15 апреля 2019

Я использую Ramda в качестве вспомогательной библиотеки для функционального программирования при создании приложения React.

Я пытаюсь построить себя whereAny. Рамда выставляет where, который проверяет, удовлетворяет ли каждый пропеллер, который ему дан, соответствующий предикат.

Я хочу создать функцию, которая принимает массив ключей, объект и поисковый термин, и если любой из ключей (значения которых являются строками) включает поисковый термин, он должен возвращать true. Если нет, он должен вернуть false.

Вот мой текущий обходной путь:

export const whereAny = keys => obj => searchTerm =>
  R.any(
    R.pipe(
      R.toLower,
      R.includes(R.toLower(searchTerm))
    ),
    R.values(R.pick(keys, obj))
  );
export const contactNameIncludesSearchValue = whereAny(['firstName', 'lastName']);

Как вы можете видеть, я использую его, чтобы увидеть, включают ли некоторые значения контакта поисковый термин (IRL я использую больше, чем просто firstName и lastName).

Мой вопрос: как вы можете создать такую ​​функцию whereAny? Я заглянул в кулинарную книгу Рамды и в Google и не смог найти рецепт для whereAny.

Проблема с моим обходным решением (за исключением того факта, что он, вероятно, не оптимален), заключается в том, что вы не можете указать различные функции, как в where. Так что в идеале мой API должен выглядеть так:

const pred = searchValue => R.whereAny({
  a: R.includes(searchValue),
  b: R.equals(searchValue),
  x: R.gt(R.__, 3),
  y: R.lt(R.__, 3)
});

Ответы [ 3 ]

2 голосов
/ 15 апреля 2019

Я думаю, что вы должны карри свои функции, используя Рамда curry.

Почему?

С этой формой карри необходимо Называйте это так и только так:

const abc = a => b => c => a + b + c;
abc(1)(2)(3); // 6

В то время как с этой формой вы более гибки:

const abc = curry((a, b, c) => a + b + c);
abc(1, 2, 3); // 6
abc(1, 2)(3); // 6
abc(1)(2)(3); // 6

Также обратите внимание, что функции Ramda, как правило, принимают данные, с которыми работаютв качестве последнего параметра:

Функции Ramda автоматически каррируются.Это позволяет вам легко создавать новые функции из старых, просто не задавая конечные параметры.

Параметры для функций Ramda расположены так, чтобы было удобно их использовать для каррирования.Данные, с которыми нужно работать, обычно предоставляются последними.

Последние две точки вместе позволяют очень легко строить функции в виде последовательности более простых функций, каждая из которых преобразует данные и передает их следующей.Ramda разработан для поддержки этого стиля кодирования.

Cf домашняя страница проекта

Я думаю, что мы все еще можем использовать этот подход для решения вашей проблемы:

const whereAny = curry((keys, search, obj) =>
  compose(includes(search), props(keys))
    (obj));
    
const whereNameIsFoo = whereAny(['firstName', 'lastName'], 'foo');

console.log(whereNameIsFoo({firstName: 'john', lastName: 'foo'}));
console.log(whereNameIsFoo({firstName: 'bar', lastName: 'baz'}));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
<script>const {curry, compose, flip, includes, props} = R;</script>
2 голосов
/ 15 апреля 2019

Я бы, вероятно, использовал ответ от Аадит М Шах, но вы также можете смоделировать его на реализации where

const whereAny = R.curry((spec, testObj) => {
  for (let [key, fn] of Object.entries(spec)) {
    if (fn(testObj[key])) {return true}
  }
  return false
})

const pred = searchValue => whereAny({
  a: R.includes(searchValue),
  b: R.equals(searchValue),
  x: R.gt(R.__, 3),
  y: R.lt(R.__, 3)
});

console.log(pred("hello")({ a: [], b: "hola", x: 3, y: 2 }));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
2 голосов
/ 15 апреля 2019

Вот что я хотел бы сделать:

const fromPair = R.apply(R.objOf);

const whereFromPair = R.compose(R.where, fromPair);

const whereAny = R.compose(R.anyPass, R.map(whereFromPair), R.toPairs);

Просто протестировал его и он работает.

...