【问题标题】:Can I make this function defenition even shorter?我可以让这个功能定义更短吗?
【发布时间】:2014-11-28 11:09:43
【问题描述】:

我正在尝试在我的 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

【问题讨论】:

  • 这不一定是我想做的。我想了解 FP,如果我知道这是可能的,那么我可以在很多地方使用它。如果我知道它不是,那么我就不会(一直)为考虑是否可以改进我的代码而烦恼。
  • @Cerbrus 在阅读了您的第二条评论后,我认为您不理解问题和/或主题。
  • 好的,为什么你想用这个库来做?为什么要“更多地转向函数式编程”

标签: javascript functional-programming currying ramda.js


【解决方案1】:

您正在寻找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');

【讨论】:

  • 似乎不起作用,检查更新的 plnkr(与问题相同的链接)。
  • Plnkr 对我不起作用,但我仍在测试;你可能是对的
  • 实际上findWithId(5)([{_id:3}, {_id:5}]) 似乎对我有用
  • 啊,但不是 findWithId(5,[{_id:3}, {_id:5}])。一个函数接受两个参数。你有一个接受一个参数的函数,它返回另一个也接受一个参数的函数。
  • 是的,因为 compose 可以使用 curried 函数...您可以从类型签名中看到 compose find hasId 为您提供了一个采用 a (= p) 的函数,a 返回一个c - 即 = ([i] -> i|undefined)
【解决方案2】:

Ramda 确实有一个函数可以帮助解决这个问题,一个叫做 useWith 的函数。如果你能想到一个更好的名字,我会喜欢的。我有asked that before

你可以这样使用:

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,参数由调用每个提供的处理程序的结果组成在新函数的连续参数上"

【讨论】:

  • 太棒了。作为 FP 的新手,我只想知道“useWith”是一个通用概念还是特定于 ramda。
  • 我做了ask that question,但似乎没有人有好的答案。部分问题在于,对于像 Haskell 这样的语言,每个函数只接受一个参数,这从来都不是问题,我认为这个问题只会导致混乱。
猜你喜欢
  • 1970-01-01
  • 2021-05-02
  • 2020-07-01
  • 2017-11-06
  • 2011-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多