admin管理员组文章数量:1279185
What is the difference between chain()
(from ramda
package) and map()
in Javascript?
In both functions the programmer inputs an object and some lambda/function and gets a certain calculation of it. Thanks.
What is the difference between chain()
(from ramda
package) and map()
in Javascript?
In both functions the programmer inputs an object and some lambda/function and gets a certain calculation of it. Thanks.
Share Improve this question edited Jul 27, 2018 at 21:47 James Conkling 3,6634 gold badges26 silver badges37 bronze badges asked Apr 16, 2018 at 15:44 J. DoeJ. Doe 958 bronze badges 7-
2
chain
isn't a native JS method on the Array.prototype – Sterling Archer Commented Apr 16, 2018 at 15:45 -
chain
is from ramda – J. Doe Commented Apr 16, 2018 at 15:45 - Can you edit your question with that knowledge and tag so that people aren't confused, please? – Sterling Archer Commented Apr 16, 2018 at 15:46
- @SterlingArcher I understand. But except for it, are these functions equivalent? – J. Doe Commented Apr 16, 2018 at 15:47
- 2 According to the documentation no. "chain maps a function over a list and concatenates the results. chain is also known as flatMap in some libraries" – Sterling Archer Commented Apr 16, 2018 at 15:48
2 Answers
Reset to default 14Abstract Types
chain
and map
each operate on an abstract type. map
operates on any Functor. This is any item with a map
function that obeys certain laws. chain
operates on a Chain element. Similarly, this is something with a lawful chain
function, as well as having lawful apply
and map
functions.
Ramda provides map
and chain
functions that will work with types fulfilling these contracts. It also supplies implementation for certain built-in types (functions, arrays, and objects for map
and functions and arrays for chain
.)
To see how they differ, it's simple enough to pare their signatures:
// map :: Functor f => (a → b) → f a → f b
// chain :: Chain m => (a → m b) → m a → m b
You can think about it like this: the function supplied to map
takes an item of type A and returns one of type B. map
accepts that function and a container holding type A and returns a container holding type B. The function supplied to chain
by contrast takes an item of type A and returns a container holding type B. chain
accepts that function and a container holding type A, returning a container holding type B.
You can think about it as though chain
unwraps one level of containers pared to map
.
Some Examples
For example, let's say we had a function factors
, which returns the factors of an integer (factors(14) //=> [1, 2, 7, 14]
, for instance.) Here is how map
and chain
would work on a list of numbers:
map(factors, [12, 15]) //=> [[1, 2, 3, 4, 6, 12], [1, 3, 5, 15]]
chain(factors, [12, 15]) //=> [1, 2, 3, 4, 6, 12, 1, 3, 5, 15]
Or if we had a Maybe
type used to simplify null-handling with the subtypes Just
to signify a value and Nothing
to signify some null in the putation. We might write a safe square root function such as
const sqrt = (n) => n > 0 ? Just(Math.sqrt(n)) : Nothing()
Then we see these differences between map
and chain
.
map(sqrt, Just(25)) //=> Just(Just(5))
chain(sqrt, Just(25)) //=> Just(5)
map(sqrt, Just(-25)) //=> Just(Nothing)
chain(sqrt, Just(-25)) //=> Nothing
And finally, for functions, for reasons described in another SO answer,
map(f, g) //~> x => f(g(x));
chain(f, g) //~> x => f(g(x))(x);
Summary
You can see from their signatures, that there is some relationship between map
and chain
, but they are distinct functions, used for very different purposes. chain
is related to what is sometimes called flatMap
, as it flattens out (one level) of the sort of result created by map
.
But the best way to think about them is to look at the signatures and the laws tied to these functions.
Update August 2019
Agree entirely with Scott's answer ;) Wished to add a simple example by way of parison. Let’s say you had a collection of friends who all had several favourite foods. We can use chain (aka flatMap) to create an array of all the foods you should serve at your next party.
import * as R from "ramda";
const friends = [
{
name: "Jill",
favoriteFoods: ["pizza", "hummus"]
},
{
name: "Bob",
favoriteFoods: ["ice cream"]
},
{
name: "Alice",
favoriteFoods: ["chicken wings", "salmon"]
}
];
let favouriteFoods = R.map(friend => friend.favoriteFoods);
console.log(favouriteFoods(friends));
//-> [ [ 'pizza', 'hummus' ], [ 'ice cream' ], [ 'chicken wings', 'salmon' ] ]
favouriteFoods = R.chain(friend => friend.favoriteFoods);
console.log(favouriteFoods(friends));
//-> [ 'pizza', 'hummus', 'ice cream', 'chicken wings', 'salmon' ]
A mon pattern is to bine a flattening function with a mapping one. You could explicitly map then flatten in 2 separate steps. Chain, however, does both for you.
本文标签: javascriptdifference between chain() and map() in ramdajsStack Overflow
版权声明:本文标题:javascript - difference between chain() and map() in ramda.js - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741219250a2360646.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论