0

Моя цель - создать пользовательскую функцию карты, которая сначала должна отфильтровать список, чтобы остаться, например, только четные элементы, прежде чем вызывать предоставленную функцию для каждого элемента. Мне нужна функция, которая должна быть карри, и для первого параметра должна быть функция, а не список. Я считаю, что подпись будет выглядеть так: (a -> b) -> [a] -> [b]Idiomatic Ramda для генерации функций более высокого порядка?

Есть, конечно, много способов сделать это. Вот как выглядела моя первая попытка.

var isEven = x => x % 2 === 0; 

var filterEvensMap = R.curry((fn, items) => R.map(fn, R.filter(isEven, items))); 

filterEvensMap(R.negate, [1,2,3,4]); // [-2, -4] 

Однако, поскольку выше использует анонимную функцию с «параметрами клея» fn и items, я не уверен, что это так, что Ramda был предназначен для использования.

Ниже я включил другой способ сделать это. Кажется, это больше в духе Рамды, но я не уверен, что я слишком усложняю ситуацию.

var filterEvensMap = R.compose(
    R.flip, 
    R.uncurryN(2) 
)(R.compose(
    R.flip(R.map), 
    R.filter(isEven) 
)); 

Я злоупотребляю несколькими композитами и небрежными? Есть ли более идиоматический способ достичь этого? По вашему опыту, имеет ли это значение?

Заранее спасибо.

ответ

2

Если вы найдете подписи Haskell полезными, вы можете найти это point-free generator (source) тоже полезно. Если вы хотите, чтобы упростить выражение можно ввести эквивалент Haskell в код JS:

filterEvensMap = \fn items -> map fn (filter isEven items) 

И это даст вам точечно бесплатно эквивалент:

filterEvensMap = (. filter isEven) . map 

Затем перевести обратно в JS с помощью Ramda :

var filterEvensMap = R.curry(R.compose(R.compose(R.filter(isEven)), R.map)) 

В вашем опыте, это имеет значение?

Я бы пошел с наиболее читаемым выражением, которое в данном случае, вероятно, является оригинальным выражением. Беспошлинная забава и может добавить ясность в некоторых местах, но она также может значительно уменьшить читаемость или, по крайней мере, уровень понимания.

+0

Эй, спасибо за советы, pointfree.js выглядит очень полезно. Однако существует небольшое несоответствие между предполагаемым поведением в OP и выражением Ramda, полученным из выражения без выражения Haskell: фильтрация должна происходить на исходных vals, а не на сопоставленных vals. Вот ссылка, которая показывает разницу: http://goo.gl/KVX4Kv. Я не знаком с синтаксисом Haskell, поэтому я все еще пытаюсь найти, где проблема. – Lopatin

+0

О, я допустил ошибку, это должно быть 'compose (pipe (filter (f)), map)', но по какой-то причине он не работает в Ramda. Я предполагаю, что авто-currying и variadic compose/pipe испортили вещи, но вы можете увидеть, как он работает в vanilla JS здесь: https://jsfiddle.net/xs56h0vb/ – elclanrs

+0

Еще раз спасибо! Я отмечаю ответ, потому что у меня есть все, что мне нужно для продолжения программирования. Я теперь знаю, что то, о чем я говорил в этом вопросе, - это понятие, называемое «pointfree», и что не всегда необходимо писать выражение в виде точки только потому, что это возможно. Но когда я хочу повеселиться, есть pointfree.js – Lopatin

 Смежные вопросы

  • Нет связанных вопросов^_^