Javascript 如何使用具有多个参数的R.pipe? 背景

Javascript 如何使用具有多个参数的R.pipe? 背景,javascript,functional-programming,ramda.js,Javascript,Functional Programming,Ramda.js,我正在学习Ramda,我正在尝试使用管道。为此,我做了一个简单的例子,但不起作用: 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

我正在学习Ramda,我正在尝试使用
管道
。为此,我做了一个简单的例子,但不起作用:

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( queryParams ),
        addAnd,
        getMarket( country ),
        R.tap( console.log ) 
    )(country, queryParams);

comp("Spain", {lang: "uk"}); //Blows Up!?
我得到的错误是

_arity的第一个参数必须是不大于零的非负整数 十有八九

​我不知道怎么解决这个问题。我怎么做


.

这是否会使代码比只使用单个函数更具可读性,这是很有争议的,但通过这种方式,您可以得到您想要的:

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"});

这是否会使代码比使用单个函数更具可读性,这是很有争议的,但通过这种方式,您可以获得所需的:

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"});

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

在我看来,最好传入一个数组,或者使用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"});

虽然我不认为
R.compose
真的能让这更容易推理。也许如果它被分离成这样一个命名函数

const enhanceQuery = R.compose(addAnd, getSQLQuery)

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

在回答核心问题“如何使用多个参数的x”时,从技术上讲,您可以使用,但这并不能立即帮助您将数据传递到管道中

在我看来,最好传入一个数组,或者使用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"});

虽然我不认为
R.compose
真的能让这更容易推理。也许如果它被分离成这样一个命名函数

const enhanceQuery = R.compose(addAnd, getSQLQuery)

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

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

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"
现在的问题是:

  • 为什么你的功能不起作用
  • 你怎么能让它工作
  • 如何使
    管道
    按需工作
  • 为什么你的功能不起作用? 它很简单:
    pipe
    将许多函数作为参数,至少需要一个。您提供的第一个参数是
    getSQLQuery(queryParams)
    ,它是使用参数调用
    getSQLQuery
    的结果。这是一个字符串,不是函数。因此,当您尝试将其包装到
    管道中时,它失败了。(关于“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"
    
    如何使
    管道
    按需工作? 您需要了解管道的功能

    考虑这样一个函数:

    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
    。过了一段时间,这就变成了第二种性质,你可以跳过第一步。

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

    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"
    
    现在的问题是:

  • 为什么你的功能不起作用
  • 你怎么能让它工作
  • 如何使
    管道
    按需工作
  • 为什么你的功能不起作用? 它很简单:
    pipe
    将许多函数作为参数,至少需要一个。您提供的第一个参数是
    getSQLQuery(queryParams)
    ,它是使用参数调用
    getSQLQuery
    的结果。这是一个字符串,不是函数。因此,当您尝试将其包装到
    管道中时,它失败了。(关于“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"
    
    如何使
    管道
    按需工作? 您需要了解管道的功能

    考虑这样一个函数:

    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
    。过了一会儿,这就成了第二天性,你可以跳过第一步。

    你想得到什么?对于初学者来说,
    pipe
    需要接收函数,并且已经对
    getSQLQuery(queryParams)
    进行了计算,因此无法获取字符串:“我的查询是英国,我的国家是西班牙