我能把这个函数辩护更短吗

Can I make this function defenition even shorter?

本文关键字:函数      更新时间:2023-09-26

我正在努力在javascript应用程序中进一步实现函数式编程。我目前使用ramda库作为这个库的基本库。

我的愿望:

  1. 创建一个函数findWithId(id, list),该函数返回列表中具有与输入id匹配的属性_id的项
  2. 使它的实现尽可能短,尽可能依赖现有的代码

迄今为止:

我的基地是拥有这种防御能力的R.find find :: (a -> Boolean) -> [a] -> a | undefined 我尝试了一些不同的解决方案,如下所示:

//Using ramdajs (ramdajs.com)
var hasId = R.curry(function(id, item) {
  return item._id === id
});
//This doesn't work
var findWithId_v1 = R.find(hasId);
//This works but can I make it as short as v1?
var findWithId_v2 = function(id, list) {
  return R.find(hasId(id), list);
}

问题

我可以使用compose、curry等标准函数式编程工具使findWithId_v2findWithId_v1一样短吗?

Plunker演示

http://plnkr.co/edit/xAYx15yk6lBzutdAL9HC?p=preview

Ramda确实有一个函数可以帮助实现这一点,它名为useWith。如果你能想出一个更好的名字,我会喜欢的。我以前问过。

你可以这样使用:

var findById = R.useWith(R.find, hasId, R.identity);
var find5 = findById(5);
find5([{id:3}, {id:5}]); //=> {id:5} 
findById(5, [{id:3}, {id:5}]); //=> {id:5} 

您不必提供上述R.identity。这也会起作用,尽管我更喜欢明确一点:

var findById = R.useWith(R.find, hasId);

useWith"接受函数fn和任意数量的transformer函数,并返回一个新函数。当调用新函数时,它会调用函数fn,其参数包括对新函数"

"的连续参数调用每个提供的处理程序的结果

您正在寻找compose函数:

compose :: (a -> b) -> (b -> c) -> (a -> c)
hasId :: p -> (i -> Boolean)
find :: (i -> Boolean) -> ([i] -> i | undefined)
compose :: (p -> (i -> Boolean))
           -> ((i -> Boolean) -> ([i] -> i | undefined))
           -> (p -> ([i] -> i | undefined))
compose find hasId :: p -> ([i] -> i | undefined)

所以你应该做

var findWithId = R.compose(R.find, hasId)

哦,请注意,hasId也不需要函数表达式:

var hasId = R.propEq('_id');