Ramda:有没有办法在管道过程中将参数“分叉"给两个函数? [英] Ramda: Is there a way to 'fork' a parameter to two functions during pipe?

查看:78
本文介绍了Ramda:有没有办法在管道过程中将参数“分叉"给两个函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是函数编程初学者.我正在使用Ramda开发一个React Native应用程序.该应用程序使用户可以维护自己的房屋.

I'm a functional programming beginner. I'm working on a React Native app using Ramda. The app lets users maintain their houses.

我编写了名为asyncPipe的函数,该函数可用于传递承诺和常规函数.我将它用于loginFlow,它目前具有http请求(getHouseList)作为其最后一个功能.

I have written function called asyncPipe which lets me pipe promises and normal functions. I use it for the loginFlow which currently has a http request (getHouseList) as its last function.

const asyncPipe = (...fns) => x => fns.reduce(async (y, f) => f(await y), x);

const loginFlow = asyncPipe(
  // ... someFunctions
  getHouseList
);

// used later like this in LoginForm.js's handleSubmit():
const list = await loginFlow(credentials);

因此,登录后,该应用程序将加载用户的房屋.现在,根据他是否只有一栋或多栋房屋,我想向用户发送列表视图以选择房屋,或者如果他只有一栋房屋,则向用户发送详细视图.另外,我想分派Redux操作以将列表保存在我的reducer中,如果要进行分派,则要分派另一个操作.

So, after logging in, the app loads the user's houses. Now depending on whether he has only one or multiple houses I would like to send the user either to list view to choose a house or a detail view if he only has one house. Additionally, I would like to dispatch a Redux action to save the list in my reducer and another action to pick the house if there is only one.

目前我是这样的:

const list = await loginFlow(credentials);
dispatch(addHouses(list));
if (list.length > 1) {
  navigate('ListScreen')
} else {
  dispatch(pickHouse(list[0]);
  navigate('DetailScreen') ;
}

但是正如您所看到的那样,这势在必行.似乎我必须分叉"列表并在管道中使用两次(因为Redux'dispatch没有返回值).

But as you can see that is super imperative. It seems like I have to 'fork' the list and use it twice in the pipe (because Redux' dispatch does not have a return value).

我的主要问题是:

如何(如果可以的话)使它更具功能性?

How to do this more functional / declaratively (if there is a way)?

我要问的一个小问题是,是否可以在这里/使其具有功能性是一个好主意.

A little sub question I have would be, whether its okay to be imperative here / if doing it functional is a good idea.

推荐答案

您可以使用

You could probably extend your async pipeline, using something like tap:

const loginFlow = asyncPipe(
  // ... some functions
  getHouseList,
  tap(compose(dispatch, addHouses)),
  tap(unless(list => list.length > 1, list => dispatch(pickHouse(list[0])))),
  list => navigate(list.length > 1 ? 'ListScreen' : 'DetailScreen', list)
);

这是否值得做取决于您的应用程序.如果管道已经很长,那么以这种方式添加内容可能会更干净,即使它们不是特别有用的部分.但是对于较短的管道,这可能没有多大意义.

Whether this is worth doing will depend upon your application. If the pipeline is already a longish one, then it would probably be cleaner to add things to the end this way, even if they're not particularly functional sections. But for a short pipeline, this might not make much sense.

您可能还想看看现在已弃用的 pipeP 或它的替代版本, pipeWith ( then ).

You also might want to look at the now-deprecated, pipeP or its replacement, pipeWith(then).

但是您在标题中询问了关于派生参数的问题. Ramda的 converge 确实做到了:

But you asked in the title about forking a parameter. Ramda's converge does exactly that:

converge(f, [g, h])(x) //=> f(g(x), h(x))

这还允许您传递两个以上的函数,并将多个参数传递给结果函数:

This allows you to pass more than two functions as well, and to pass more than one parameter to the resulting function:

converge(f, [g, h, i])(x, y) //=> f(g(x, y), h(x, y), i(x, y)) 

这篇关于Ramda:有没有办法在管道过程中将参数“分叉"给两个函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆