如何将多个参数传入Ramda撰写链?

Ami*_*ole 4 functional-programming function-composition ramda.js

以下是我尝试将四个函数组合成一个端点字符串:

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')
Run Code Online (Sandbox Code Playgroud)

这个组合工作并返回我想要的结果:

https://api.content.io?sort=desc&part=true&query={ some:'value', another:'value'}
Run Code Online (Sandbox Code Playgroud)

但请注意我是如何对其函数体内部和内部的值进行硬编码的.我看到只有一个值超过了这个链中的值.paramsqueryR.compose

我如何以及在何处将参数传递给参数和查询参数?

更新:

我做的是curried那些函数:

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)}` )
Run Code Online (Sandbox Code Playgroud)

然后

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);
Run Code Online (Sandbox Code Playgroud)

但最后的召唤result仍然看起来非常黑客和不优雅.有没有办法改善这个?

Sco*_*yet 6

我如何以及在何处将参数传递给参数和查询参数?

老实说,你没有,不是在你使用Ramda或类似的库构建composepipe管道时.

Ramda(免责声明:我是作者之一)允许第一个函数接收多个参数 - 一些其他库执行,一些不执行 - 但后续函数只接收先前调用的结果.还有一个功能保护区,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"
Run Code Online (Sandbox Code Playgroud)

我真的不知道你对最后一个参数的要求.没有它encodeUriComponent,我看起来很奇怪,但也许你不需要它.我还对第二个参数采取了自由,假设您更喜欢API中的实际数据到封装该数据的字符串.但是,如果你通过'sort=desc&part=true',然后替换pipe(toPairs, map(join('=')), join('&'))identity.

由于整个事情远非无点,我可能没有使用第一个函数的无点版本or(__, 'default'),因为我认为有更多可读性.

更新

您可以在Ramda REPL上看到这个版本,其中添加了一些console.log语句tap.


这确实为Ramda提出了一个有趣的问题.如果这些中间函数确实是可取的,那么Ramda无法将它们组合起来.显然拉姆达可以提供类似的东西meld,但是有中间立场吗?我想知道是否有一个有用的功能(当然是咖喱),我们应该包含类似的功能

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)
// ...
Run Code Online (Sandbox Code Playgroud)

有一些严重的反对意见:如果名单长度不同怎么办?为什么初始调用是一元的,我们应该通过向函数添加单独的累加器参数来解决这个问题吗?尽管如此,这是一个有趣的功能,我可能会提出它来讨论Ramda板.


Mad*_*Nat 1

如果您有参数和查询作为柯里化函数,那么您可以:

编辑:具有所有花哨功能的代码,需要更改参数顺序或使用R.__和字符串化对象

const endpoint = R.curry( str => `${str}` || 'default' )
const protocol = R.curry( str => `https://${str}` )
const params = R.curry( (p, str) => `${str}?${p}` )
const query = R.curry( (q, str) => `${str}&query=${q}` )

let finalEndpoint =
    R.compose(
        query(JSON.stringify({ some:'value', another:'value' })),
        params('sort=desc&part=true'),
        protocol,
        endpoint
    )
var result = finalEndpoint('api.content.io')
console.log(result)
Run Code Online (Sandbox Code Playgroud)