I learned this one time when digging into the source code for the Elixir language. The Enum module there has map(), filter(), and reduce() -- but both map and filter are defined as reduce functions.
Perl 6 doesn't do it this way, because it can't do that easily.
If you tried to implement map with reduce it would hang before producing a single value when called on an infinite sequence.
my @a = (0..Inf).map( *² ); # infinite sequence of all squared values
.say() for @a.head(20); # prints first twenty squares
# sequence of only twenty squared values
my @b = (0..^20).reduce: { @_.head(*-1).Slip, @_.tail² }
.say() for @b; # prints the same twenty squares
# doesn't stop until it is killed or runs out of resources
my @c = (0..Inf).reduce: { @_.head(*-1).Slip, @_.tail² }
.say() for @c.head(20); # never gets to this line of code
You could maybe find a way to pass upwards the number of values to produce:
my @d = (0..Inf).reduce: {
last if @_ > 20; # stop early
@_.head(*-1).Slip, @_.tail²
}
.say() for @d;
The thing is that iteration is done using an object based protocol, so map and grep just return an object with the appropriate functionality.
(Most of the time this is abstracted away so you don't need to know how it works.)
Perl 6 is a functional language while also being a procedural language.
So it can't always make the same sort of guesses about what you mean that pure functional languages can make.
Cofounded Host Collective (DiscountASP.net). Cofounded Player Axis (Social Gaming). Computer Scientist and Technology Evangelist with 20+ years of experience with JavaScript!
And I could show you a real use case for this. I have created MojiScript and implemented map, filter and reduce. Both map and filter internally call reduce. Here's some examples:
Cofounded Host Collective (DiscountASP.net). Cofounded Player Axis (Social Gaming). Computer Scientist and Technology Evangelist with 20+ years of experience with JavaScript!
While reduce can pretty much do anything, I would recommend that you also mention that not to use the same hammer for every kind of nail. We developers like to stay in our familiar territory and that’s why we avoid trying out new things, it would really suck if a fellow developer uses reduce to do everything, when they could have used other more optimised things.
You are absolutely correct. I eluded to the fact that map and filter were more optimized than their reduce implementations, but I need to reiterate that at the end. Thanks for the feedback!
Nice article. I was recently trying out some coding problems using javascript. Array.reduce was very useful in solving them in a functional way. It is similar to fold in Haskell. This is a great article on the power of folds in Haskell.
Thank you for stopping by! I am a full-stack developer that combines the power of entrepreneurship and programming to make the lives of programmers easier.
I used filter, map and reduce almost every day at work and never thought of that! Great article!
Maybe use reduce instead when you both want to filter and map at the same time? Or maybe you want to do some other operations as well. reduce is like the swiss army knife of JS.
Nice! I had a few other functions I thought about implementing (takeWhile and every were on my list), but I opted not to in order to keep the article brief. I'm glad that you took the time to show those implementations in your article!
I'm a very straightforward data science student in last year before master graduation. I like to learn bottom-up step by step and go through the logical discovery process myself as much as possible
I remember doing the implementation of map and fikter if I remember correctly, it was in scala. Whatever, map and filter are good because they are cornerstones of the bridge between high order abstraction and intuition
Before anyone would be inclinded to use reduce for everything, since it indeed can be used to do all the things that mapand filter(as well as someand any), keep in mind that the same could be said (and then some) about a traditional for loop.
As to using reduce when you want to combine different operations, again note that the same would be true for a forloop. Neither a for loop nor reduceshould be used in those cases, for the very same reason: you sacrifice legilibity (and the next developer that has to modify your code won't be thanking you for your cleverness).
In JavaScript, there would be a slight performance hit if you used reduce to perform a map operation because of returning an array each time. However, immutable data structures in other languages (like Clojure's vector) would not really see a performance hit because of how they are stored. You've given me an idea on a follow up post to discuss immutability and lazy vs. eager evaluation. Thanks for the feedback!
I learned this one time when digging into the source code for the Elixir language. The Enum module there has map(), filter(), and reduce() -- but both map and filter are defined as reduce functions.
You can see it over here:
github.com/elixir-lang/elixir/blob...
I wouldn't be surprised if every other language does the same, now that I think about it.
So, yeah, write the code that reads the best for the sake of future coders, and the language will take care of simplifying the rest for you. ;-)
Perl 6 doesn't do it this way, because it can't do that easily.
If you tried to implement
mapwithreduceit would hang before producing a single value when called on an infinite sequence.You could maybe find a way to pass upwards the number of values to produce:
The thing is that iteration is done using an object based protocol, so
mapandgrepjust return an object with the appropriate functionality.(Most of the time this is abstracted away so you don't need to know how it works.)
Perl 6 is a functional language while also being a procedural language.
So it can't always make the same sort of guesses about what you mean that pure functional languages can make.
I'm just now digging into Elixir/OTP, and I'm actually kind of amused to see that 😀 thanks for pointing that out!
Great article!
And I could show you a real use case for this. I have created MojiScript and implemented map, filter and reduce. Both map and filter internally call reduce. Here's some examples:
github.com/joelnet/MojiScript/blob...
github.com/joelnet/MojiScript/blob...
Well technically they (and also
reduce) callreduceWhile.Glad you enjoyed it! And it looks like I'm going to have to invest some time in checking out MojiScript. It looks like it could have some legs!
lol I would agree with you on MojiScript, but I am obviously biased ;)
While reduce can pretty much do anything, I would recommend that you also mention that not to use the same hammer for every kind of nail. We developers like to stay in our familiar territory and that’s why we avoid trying out new things, it would really suck if a fellow developer uses reduce to do everything, when they could have used other more optimised things.
You are absolutely correct. I eluded to the fact that map and filter were more optimized than their
reduceimplementations, but I need to reiterate that at the end. Thanks for the feedback!Nice article. I was recently trying out some coding problems using javascript.
Array.reducewas very useful in solving them in a functional way. It is similar tofoldin Haskell. This is a great article on the power of folds in Haskell.I hadn't read that particular paper yet, but now it's on my list 😊 Thanks for the recommendation!
I used
filter,mapandreducealmost every day at work and never thought of that! Great article!Maybe use
reduceinstead when you both want to filter and map at the same time? Or maybe you want to do some other operations as well.reduceis like the swiss army knife of JS.Glad to know that I have an idea in common with such an experienced developer. I had also written an article on LinkedIn regarding this approach.
Nice! I had a few other functions I thought about implementing (
takeWhileandeverywere on my list), but I opted not to in order to keep the article brief. I'm glad that you took the time to show those implementations in your article!I remember doing the implementation of map and fikter if I remember correctly, it was in scala. Whatever, map and filter are good because they are cornerstones of the bridge between high order abstraction and intuition
Before anyone would be inclinded to use
reducefor everything, since it indeed can be used to do all the things thatmapandfilter(as well assomeandany), keep in mind that the same could be said (and then some) about a traditionalforloop.As to using reduce when you want to combine different operations, again note that the same would be true for a
forloop. Neither aforloop norreduceshould be used in those cases, for the very same reason: you sacrifice legilibity (and the next developer that has to modify your code won't be thanking you for your cleverness).Using reduce instead of map won't be returning a new array on each iteration? Therefore lesser performance?
In JavaScript, there would be a slight performance hit if you used
reduceto perform amapoperation because of returning an array each time. However, immutable data structures in other languages (like Clojure'svector) would not really see a performance hit because of how they are stored. You've given me an idea on a follow up post to discuss immutability and lazy vs. eager evaluation. Thanks for the feedback!Thank you!
For the lulz you could write
pushAndReturnas: