如何使用R.pipe多个参数?

时间:2018-01-09 11:49:55

标签: javascript functional-programming ramda.js

背景

我正在学习Ramda,我正在尝试使用rgb(0, 128, 0)。为此,我做了一个不起作用的简单示例:

pipe

我得到的错误是

  

_arity的第一个参数必须是非负整数,不能更大   十点以上

我不知道如何解决这个问题。我该怎么办?

You can see it live here

3 个答案:

答案 0 :(得分:5)

有很多方法可以编写这样的功能。我知道您的目标是学习如何使用pipe,但让我首先展示一种技巧,从类似于您的功能开始:

const getSQLQuery = ( { lang } ) => `My query is ${lang}`;
const getMarket = country => `my country is ${country}`;
const flipAndJoin = pipe(reverse, join(' and '))

const comp = useWith(unapply(flipAndJoin), [getMarket, getSQLQuery])

comp("Spain", {lang: "uk"}); //=> ""My query is uk and my country is Spain"

现在的问题是:

  1. 为什么你的功能不起作用?
  2. 你怎么能让它发挥作用?
  3. 如何让pipe按需运作?
  4. 为什么你的功能不起作用?

    很简单:pipe将许多函数作为参数,至少需要一个。您提供的第一个参数是getSQLQuery( queryParams ),它是使用参数调用getSQLQuery结果。这是一个字符串,而不是一个函数。因此,当您尝试将其包装在pipe中时,它会失败。 (关于'arity'的注释与Ramda的内部有关:它使用第一个函数pipe来确定结果函数应该采用多少参数。)

    你怎么能让它发挥作用?

    我在上面给出了答案。 MarioF的答案是这样做的,对你的初始功能的改动很小。

    但这些都不如

    那么简单
    const comp2 = (country, queryParams) => 
                  `My query is ${queryParams.lang} and my country is ${country}`
    
    comp2("Spain", {lang: "uk"}); //=> ""My query is uk and my country is Spain"
    

    如何使pipe按需运作?

    您需要了解pipe的作用。

    想想这样的函数:

    const getUpperAddr(userName, collection) {
        const configStr = getUserConfig(userName, collection);
        const config = JSON.parse(configStr);
        const address = prop('address')(config);
        const addrLine1 = prop('addrLine1')(address);
        const upperAddr = toUpper(addrLine1);
        return upperAddr;
    }
    

    忘记细节,特别是getUserConfig如何工作,忘记任何潜在的错误,我们可以看到这个函数的一个有趣的特征:每个连续的局部变量是通过将函数应用于之前的函数来创建的。唯一的例外是第一个,它使用函数的参数。结果是最终的局部变量。

    pipe只是一种使这更具说明性的方法,并且不再需要所有局部变量(甚至参数名称。)这是等效的:

    const getUpperAddr = pipe(
        getUserConfig,
        JSON.parse,
        prop('address'),
        prop('addrLine1'),
        toUpper
    );
    

    它具有与上面相同的签名,并为同一输入返回相同的结果。如果您可以用第一种格式编写函数,则可以机械地更改为pipe。过了一会儿,这成了第二天,你可以跳过第一步。

答案 1 :(得分:1)

这是否足以说明这是否使代码比仅使用单个函数更具可读性,但这样您就可以获得所需内容:

var getSQLQuery = (_, {lang}) => `My query is ${lang}`;
var addAnd = str => str + " and";
var getMarket = country => data => `${data} my country is ${country}`;

var comp = ( country, queryParams ) => R.pipe( 
    getSQLQuery,
    addAnd,
    getMarket( country ),
    R.tap( console.log ) 
)(country, queryParams);

comp("Spain", {lang: "uk"});

答案 2 :(得分:1)

在回答核心问题“如何使用带有多个参数的x”时,从技术上讲,您可以使用R.nthArg,但这并不会立即帮助您将数据传递给管道。

在我看来,最好传入一个数组 - 或者使用 rest参数。这有效:

//Kept as original
var getSQLQuery = ( { lang } ) => `My query is ${lang}`;
var addAnd = str => str + " and";
var getMarket = country => data => `${data} my country is ${country}`;

//only modified this function
const comp = (...args) => 
  getMarket(args[0]) (
    R.compose(addAnd, getSQLQuery)(args[1])
  );

comp("Spain", {lang: "uk"});

Repl here

虽然我不认为R.compose真的让人更容易理解。也许如果将它分成这样的命名函数?

const enhanceQuery = R.compose(addAnd, getSQLQuery)

const comp = (...args) => 
  getMarket(args[0]) (enhanceQuery(args[1]));

Repl here