我如何将多个参数传递到Ramda撰写链中? [英] How do I pass in multiple parameters into a Ramda compose chain?
问题描述
这里有四个函数,我试图将它们组合到一个单独的端点字符串中:
const endpoint = str => `$ {str}`|| 'default'
const protocol = str => `https:// $ {str}`
const params = str => `$ {str}?sort = desc& part = true&`
const query = str => `$ {str} query = {some:'value',another:'value'}`
let finalEndpoint = R.compose(query,params,protocol,endpoint)
var result = finalEndpoint('api.content.io')
这个组合工作并返回结果我想要的是:
https://api.content.io?sort=desc&part=true&query= {some:'value',another:'value'}
但请注意我的在它们的函数体内为 params
和查询
进行硬编码。我发现只有一个值在这个 R.compose
链中的值上升。
传入参数的方法和参数传递给参数和查询参数?
更新:
我所做的是这样的功能:
var R = require('ramda');
const endpoint = str => `$ {str}`|| 'default'
const protocol = str => `https:// $ {str}`
const setParams = R.curry((str,params)=>`$ {str}?$ {params}`)
const setQuery = R. curry((str,query)=>`$ {str}& query = $ {JSON.stringify(query)}`)
然后是
let finalEndpoint = R.compose(协议,端点)
var result = setQuery(setParams(finalEndpoint('api.content.io'),'sort = desc& part = true'),{some:'value',another:'value'})
console.log(result);
但最终调用get result 仍然似乎很黑,不雅。有什么方法可以改善这种情况?
在参数参数参数和查询参数?
老实说,你没有,当你建立一个撰写
或管道
与Ramda或类似库的管道。
Ramda(免责声明:我是其中一位作者)允许第一个函数接收多个参数 - 其他一些函数库,有些不这样做 - 但后来的函数只会接收以前调用的结果。 Sanctuary 中有一项功能, meld
,这可能对此有所帮助,但确实有相当复杂的API。
然而,我不明白为什么你要以这种方式建立这个功能。这些中间函数实际上是可重用的,还是您按照规范构建它们?我问的原因是,这似乎是一个相同的想法更明智的版本:
const finalEndpoint = useWith(
(endpoint,params,query)=>`https:// $ {endpoint}?$ {params}& query = $ {query}`,[
endpoint => endpoint ||'default',
pipe(toPairs,map(join('=')),join('&')),
pipe(JSON.stringify,encodeURIComponent)
]
);
finalEndpoint(
'api.content.io',
{sort:'desc',part:true},
{some:'value',another :'value'}
);
// => https://api.content.io?sort=desc&part=true&query=%7B%22some%22%3A%22value%22%2C%22another%22%3A%22value%22%7D
我不太了解您对最后一个参数的要求。没有 encodeUriComponent
,看起来很奇怪,但也许你不需要它。而且我还采用了第二个参数,假设您更喜欢将API中的实际数据转换为封装该数据的字符串。但是,如果您希望传递'sort = desc& part = true'
,则将 pipe(toPairs,map(加入('=')),加入('&'))
与身份
。
由于整个事情远没有点无关,所以我没有使用第一个函数的无点版本,可能是或(__,'default')
,因为我认为有更多可读性。
更新
您可以在 Ramda REPL ,它通过 console.log 语句
$ b
这对Ramda提出了一个有趣的问题。如果这些中间功能真的是可取的,拉姆达没有办法将它们结合起来。很明显拉姆达可以提供类似于 meld
的东西,但是有一个中间立场?我想知道是否有一个有用的函数(curried,当然),我们应该包含这样的工作:
someFunc [f0],[a0]); // => f0(a0)
someFunc([f0,f1],[a0,a1]); // => f1(f0(a0),a1)
someFunc([f0,f1,f2],[a0,a1,a2]); // => f2(f1(f0(a0),a1),a2)
someFunc([f0,f1,f2,f3],[a0,a1,a2,a3]); // => f3(f2(a0),a1),a2),a3)
// ...
有一些严重的反对意见:如果列表的长度不同,会怎么样?为什么初始调用是一元的,我们是否应该通过为函数添加一个单独的累加器参数来解决这个问题?尽管如此,这是一个有趣的功能,我可能会在Ramda板上讨论它。
Here are four functions I am trying to compose into a single endpoint string:
const endpoint = str => `${str}` || 'default'
const protocol = str => `https://${str}`
const params = str => `${str}?sort=desc&part=true&`
const query = str => `${str}query={ some:'value', another:'value'}`
let finalEndpoint = R.compose(query, params, protocol, endpoint)
var result = finalEndpoint('api.content.io')
This composition works and returns the result I want which is:
https://api.content.io?sort=desc&part=true&query={ some:'value', another:'value'}
But notice how I have hard coded the values for params
and query
inside their function body. I see only one value going up the value in this R.compose
chain.
How and where exactly do I pass in parameters to the params and query parameters?
UPDATE:
What I did was curried those functions like this:
var R = require('ramda');
const endpoint = str => `${str}` || 'default'
const protocol = str => `https://${str}`
const setParams = R.curry ( (str, params) => `${str}?${params}` )
const setQuery = R.curry ( (str, query) => `${str}&query=${JSON.stringify(query)}` )
and then
let finalEndpoint = R.compose(protocol, endpoint)
var result = setQuery(setParams(finalEndpoint('api.content.io'), 'sort=desc&part=true'), { some:'value', another:'value'})
console.log(result);
But the final call to get result
still seems pretty hacked and inelegant. Is there any way to improve this?
How and where exactly do I pass in parameters to the params and query parameters?
Honestly, you don't, not when you're building a compose
or pipe
pipeline with Ramda or similar libraries.
Ramda (disclaimer: I'm one of the authors) allows the first function to receive multiple arguments -- some other libraries do, some don't -- but subsequent ones will only receive the result of the previous calls. There is one function in Sanctuary, meld
, which might be helpful with this, but it does have a fairly complex API.
However, I don't really understand why you are building this function in this manner in the first place. Are those intermediate functions actually reusable, or are you building them on spec? The reason I ask is that this seems a more sensible version of the same idea:
const finalEndpoint = useWith(
(endpoint, params, query) =>`https://${endpoint}?${params}&query=${query}`, [
endpoint => endpoint || 'default',
pipe(toPairs, map(join('=')), join('&')),
pipe(JSON.stringify, encodeURIComponent)
]
);
finalEndpoint(
'api.content.io',
{sort: 'desc', part: true},
{some:'value', another:'value'}
);
//=> "https://api.content.io?sort=desc&part=true&query=%7B%22some%22%3A%22value%22%2C%22another%22%3A%22value%22%7D"
I don't really know your requirements for that last parameter. It looked strange to me without that encodeUriComponent
, but perhaps you don't need it. And I also took liberties with the second parameter, assuming that you would prefer actual data in the API to a string encapsulating that data. But if you want to pass 'sort=desc&part=true'
, then replace pipe(toPairs, map(join('=')), join('&'))
with identity
.
Since the whole thing is far from points-free, I did not use a points-free version of the first function, perhaps or(__, 'default')
, as I think what's there is more readable.
Update
You can see a version of this on the Ramda REPL, one that adds some console.log
statements with tap
.
This does raise an interesting question for Ramda. If those intermediate functions really are desirable, Ramda offers no way to combine them. Obviously Ramda could offer something like meld
, but is there a middle ground? I'm wondering if there is a useful function (curried, of course) that we should include that works something like
someFunc([f0], [a0]); //=> f0(a0)
someFunc([f0, f1], [a0, a1]); //=> f1(f0(a0), a1)
someFunc([f0, f1, f2], [a0, a1, a2]); //=> f2(f1(f0(a0), a1), a2)
someFunc([f0, f1, f2, f3], [a0, a1, a2, a3]); //=> f3(f2(f1(f0(a0), a1), a2), a3)
// ...
There are some serious objections: What if the lists are of different lengths? Why is the initial call unary, and should we fix that by adding a separate accumulator parameter to the function? Nonetheless, this is an intriguing function, and I will probably raise it for discussion on the Ramda boards.
这篇关于我如何将多个参数传递到Ramda撰写链中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!