使用 Ramda.js 进行无点函数组合

Wil*_*iam 4 javascript functional-programming ramda.js redux

我使用 Ramda.js 作为选择器函数,以访问 Redux 存储中的数据。我想要的是将我的选择器定义为不引用state选择器所作用的函数,例如:

const getUserName = path(['user', 'name']);

const name = getUserName({
  user: {
    name: 'Some Name'
  }
});
Run Code Online (Sandbox Code Playgroud)

这对于简单选择器来说很容易,但有时对于组合选择器来说会成为问题。

这是一个示例,其中一些items需要解决,由它们id在对象上引用:

const getItemById = id => state => path(['items', id], state);

const getConnectedItemIds = obj => path(['items'], obj);

const getItemsFromObj = obj => state => {
    const ids = getConnectedItemIds(obj);
    return ids.map(id => getItemById(id)(state));
};
Run Code Online (Sandbox Code Playgroud)

第一个函数可以很容易地在不引用 的情况下表达state,而第二个函数则无需引用obj,我认为这称为无点风格。但是如果没有 ,如何编写第三个函数state呢?

我正在寻找如何使用 Ramda 重写第三个函数,以及与此相关的规则和程序,例如(不知道其是否属实):

所有组合函数都需要将state其作为最后一个参数,以便能够在最终组合中将其拉出。

Sco*_*yet 5

这里已经有很多好的建议。也许最重要的是建议仅在提高可读性时才使用无点,而不是单独作为目标。

我的答案确实使用了主函数和一个助手的无点版本,但跳过了另一个函数,我认为可读性会受到影响。

const getItemById = id => path(['items', id]);

const getConnectedItemIds = prop ('items');

const getItemsFromObj = pipe (
  getConnectedItemIds, 
  map (getItemById), 
  juxt
)

const obj = {foo: 42, items: ['8', '17']}
const state = {bar: 1, items: {'6': 'a', '8': 'b', '14': 'c', '17': 'd', '25': 'e'}}

console .log (
  getItemsFromObj (obj) (state)
)
Run Code Online (Sandbox Code Playgroud)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script>const {juxt, map, path, pipe, prop} = R                      </script>
Run Code Online (Sandbox Code Playgroud)

这里重要的函数是juxt,它将函数数组应用于相同的值,返回结果数组。

getItemById是通过删除该点来对原始内容进行简化的state,但据我所知,使其无点只能以可读性为代价。其他人对此提出了建议,所有这些建议都很好,但正如他们指出的那样,没有一个像上面的那样具有可读性。我的版本看起来像这样:

const getItemById = compose (path, flip (append) (['items']));
//  or              pipe (flip (append) (['items']), path);
Run Code Online (Sandbox Code Playgroud)

我不认为它比其他答案中的建议更好或更差,但它们都不像

const getItemById = id => path(['items', id]);
Run Code Online (Sandbox Code Playgroud)

最后,如果这些辅助函数不在其他地方使用,我认为内联它们实际上可以提高可读性:

const getItemById = id => path(['items', id]);
Run Code Online (Sandbox Code Playgroud)

注意,虽然我没有在这里使用它,但我真的很喜欢 customcommander 的propOr([], 'items')for建议getConnectedItemIds的建议。它彻底消除了一个潜在的故障点。