简体   繁体   English

如何传递多个参数来组成Ramda.JS

[英]How to pass multiple arguments to compose with Ramda.JS

I'm using Ramda.js and I am struggling to accomplish a simple task. 我正在使用Ramda.js,我正在努力完成一项简单的任务。 Could someone please tell me: 1) Why it doesn't work and 2) How can I make it work 有人可以告诉我:1)为什么它不起作用2)我怎样才能使它工作

Consider the following code: 请考虑以下代码:

// Defined in utils.js
const makeArrayFromNum = num => [num]
const multByTen = num => num * 10
const multByTwo = num => num * 2
const makeThing = compose(
  map(multByTwo),
  concat,
  map(multByTen),
  makeArrayFromNum
)

// Otherfile.js
// import makeThing from .......
// Call it from a different file (does not share scope with above things)
// ---------------
// Expect to get back: [100, 18] because:
// 1) 5 -> makeArrayFromNum -> [5]
// 2) [5] -> map(multByTen) -> [50]
// 3) [50] -> concat (Still needs one arg, so pulls in [9]) -> [50, 9]
// 4) [50, 9] -> map(multByTwo) -> [100, 18]
makeThing(5, [9])

When I invoke makeThing , I first pass 5 to it. 当我调用makeThing ,我首先将5传递给它。 makeArrayFromNum accepts the 5 and everything goes smoothly... that is, until concat . makeArrayFromNum接受5并且一切顺利......也就是说,直到concat concat returns a function. concat返回一个函数。 Because concat takes 2 arguments, I would expect it to go back to my original argument list, and locate the [9] that has not been used yet. 因为concat需要2个参数,所以我希望它返回到我的原始参数列表,并找到尚未使用的[9] It does not. 它不是。

This should be a link to the Ramda REPL, with the same code I pasted above. 应该是Ramda REPL的链接,上面粘贴了相同的代码。 But at least you can run it there. 但至少你可以在那里运行它。

Thanks 谢谢

UPDATE UPDATE

The above code snippet doesn't work, but I wrote it because it demonstrates in a clear way what I'm trying to achieve. 上面的代码片段不起作用,但我写了它,因为它以清晰的方式演示了我正在尝试实现的内容。 Since it attracted the wrong kind of attention, I've included two more functioning code snippets, which also demonstrate my goal, but in an unclear and non-concise way. 由于它吸引了错误的注意力,我已经包含了两个更有效的代码片段,这也代表了我的目标,但是以一种不清楚和不简洁的方式。

Since someone in the comments said it wasn't possible to do with compose since compose only accepts unary functions, I felt I should provide a solution that I came up with to help clarify my question. 因为评论中的某些人说由于compose只接受一元函数而无法使用compose ,我觉得我应该提供一个解决方案,我想出来帮助澄清我的问题。 Hope this helps others answer my question. 希望这有助于其他人回答我的问题。

const makeThing = compose(
  map(multByTwo),
  useWith(
    concat,
    [
      compose(
        map(multByTen),
        makeArrayFromNum
      ),
     identity
    ]
  )
)
makeThing(5, [9])

And another for posterity: 后人的另一个:

const makeThing = compose(
  map(multByTwo),
  converge(
    concat,
    [
      compose(
        map(multByTen),
        makeArrayFromNum,
        head
      ),
      tail
    ]
  )
)

My original question still stands. 我原来的问题仍然存在。 What the above solutions gain in functionality, they lack in clarity and conciseness. 上述解决方案在功能上获得了什么,缺乏清晰度和简洁性。

First the following functions could be transformed as follows: 首先,可以将以下函数转换如下:

  1. num => [num] is equal to R.of num => [num]等于R.of
  2. num => num * 10 is equal to R.multiply(10) num => num * 10等于R.multiply(10)
  3. num => num * 2 is equal to R.multiply(2) num => num * 2等于R.multiply(2)

I can see two options: 我可以看到两个选项:

Have a function that returns another function 有一个返回另一个函数的函数

As you can see the function composition is "hardcoded" to the num parameter. 如您所见,函数组合对num参数进行了“硬编码”。 Note that I also slightly modified your original function composition 请注意,我还略微修改了您的原始功能组合

const makeThingFn = num =>
  compose(
    map(multiply(2)),
    flip(prepend)([num]),
    multiply(10));

const makeThing = makeThingFn(9);
makeThing(5); //=> [100, 18]

Use lenses 使用镜头

That way you can pass your array directly but have the function composition operate on specific indexes: 这样你可以直接传递你的数组但是函数组合对特定的索引进行操作:

const makeThing =
  compose(
    map(multiply(2)),
    over(lensIndex(0), multiply(10)));

makeThing([5, 9]); //=> [100, 18]

It doesn't work because compose is, quite literally, just composing the functions . 它不起作用,因为compose ,实际上只是组成函数 That means all of the parameters are passed to the last/rightmost function, then the return value of that function is passed to the next function on the list, and so on. 这意味着所有参数都传递给最后/最右边的函数,然后该函数的返回值被传递给列表中的下一个函数,依此类推。 Thus, your makeThing function is essentially this: 因此,您的makeThing函数基本上是这样的:

const makeThing = (...params) => map(multByTwo)(concat(map(multByTen)(makeArrayFromNum(...params))))

This means that makeThing(5, [9]) translates to the following call: 这意味着makeThing(5, [9])转换为以下调用:

map(multByTwo)(concat(map(multByTen)(makeArrayFromNum(5, [9]))))

Note that concat is being called with only one parameter, but it requires two. 请注意,仅使用一个参数调用concat ,但它需要两个参数。 Since Ramda functions are automatically curried, the incomplete concat returns another function that is expecting the second parameter. 由于Ramda函数是自动curry,不完整的concat返回另一个期望第二个参数的函数。 Since no second parameter is being passed, things fall apart at that point. 由于没有传递第二个参数,因此事情就会崩溃。

So how can you do it? 那你怎么能这样做呢? What you need is something like this: 你需要的是这样的:

const makeThing = (a, b) => map(multByTwo)(concat(map(multByTen)(makeArrayFromNum(a)), b))

// alternatively...
const makeThing = (a, b) => map(multByTwo)(concat(map(multByTen)(makeArrayFromNum(a)))(b))

Try it out and you'll see that it gives you the expected output. 尝试一下,你会看到它给你预期的输出。 Unfortunately, that doesn't directly translate back to compose ; 不幸的是,这并没有直接转化为compose ; the closest you can get is this: 你能得到的最接近的是:

const makeThing = (a, b) => compose(
  map(multByTwo),
  concat(b),
  map(multByTen),
  makeArrayFromNum
)(a)

You get a result that is close, but the items are reversed. 您得到的结果很接近,但项目是相反的。 Maybe there are some Ramda functions you can use to handle that, but I don't know all the functions so I can't help there. 也许有一些Ramda函数可以用来处理它,但我不知道所有函数所以我无法帮助那里。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM