Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
281 views
in Technique[技术] by (71.8m points)

javascript - Can't wrap my head around "lift" in Ramda.js

Looking at the source for Ramda.js, specifically at the "lift" function.

lift

liftN

Here's the given example:

var madd3 = R.lift(R.curry((a, b, c) => a + b + c));

madd3([1,2,3], [1,2,3], [1]); //=> [3, 4, 5, 4, 5, 6, 5, 6, 7]

So the first number of the result is easy, a, b, and c, are all the first elements of each array. The second one isn't as easy for me to understand. Are the arguments the second value of each array (2, 2, undefined) or is it the second value of the first array and the first values of the second and third array?

Even disregarding the order of what's happening here, I don't really see the value. If I execute this without lifting it first I will end up with the arrays concatenated as strings. This appears to sort of be working like flatMap but I can't seem to follow the logic behind it.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Bergi's answer is great. But another way to think about this is to get a little more specific. Ramda really needs to include a non-list example in its documentation, as lists don't really capture this.

Lets take a simple function:

var add3 = (a, b, c) => a + b + c;

This operates on three numbers. But what if you had containers holding numbers? Perhaps we have Maybes. We can't simply add them together:

const Just = Maybe.Just, Nothing = Maybe.Nothing;
add3(Just(10), Just(15), Just(17)); //=> ERROR!

(Ok, this is Javascript, it will not actually throw an error here, just try to concatenate thing it shouldn't... but it definitely doesn't do what you want!)

If we could lift that function up to the level of containers, it would make our life easier. What Bergi pointed out as lift3 is implemented in Ramda with liftN(3, fn), and a gloss, lift(fn) that simply uses the arity of the function supplied. So, we can do:

const madd3 = R.lift(add3);
madd3(Just(10), Just(15), Just(17)); //=> Just(42)
madd3(Just(10), Nothing(), Just(17)); //=> Nothing()

But this lifted function doesn't know anything specific about our containers, only that they implement ap. Ramda implements ap for lists in a way similar to applying the function to the tuples in the crossproduct of the lists, so we can also do this:

madd3([100, 200], [30, 40], [5, 6, 7]);
//=> [135, 136, 137, 145, 146, 147, 235, 236, 237, 245, 246, 247]

That is how I think about lift. It takes a function that works at the level of some values and lifts it up to a function that works at the level of containers of those values.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...