The full video and many others like it are all available as part of our Frontend Masters subscription.

Brian Lonsdorf

Brian Lonsdorf has taught several workshops and training courses on functional programming with javascript. He'a a regular speaker at conferences and helps organize/host FP events around the Bay Area.

Brian Lonsdorf

Hardcore Functional JS

Challenge 3 in this exercise requires you to create a function that finds the largest number in a list. Joe begins walking through this complex solution. He then takes a few minutes to further explain the "reduce" function.
- Problem: http://jsbin.com/romun
- Solution: http://jsbin.com/mojusuyane

Get Unlimited Access Now

Joe Nelson: So we did 1 and 2 and 3. What does 3 ask us to do? Create a function to find the largest number in a list. And what are we allowed to use? This greater thing, which we just created, which returns the greater of its two inputs. So it's saying we can do this with currying.

And one of the list functions, map, filter, or reduce. Okay, well, let's think about that first bit. Think that through first. So we want to find the greatest number in a list. Okay, that kind of rules map out, in my mind. Because if I'm given a list, and I'm operating on each cell and making a new list.

I don't want a new list, I want the biggest thing in the list. So there goes map. Filter is almost there. What if we had a way to filter out the ones that aren't the greatest? And it would give us a list with one thing. And then we could take the beginning of the list.

It's kind of complicated, whereas reduce is pretty good. Reduce is like rolling a snowball. You have this thing that you have the beginning kernel of snow. And you roll it on the ground, it gets bigger and bigger and accumulates.
Joe Nelson: And what would the snowball be? Reduce is often used to add numbers together.

You would say, I start with zero. And then the numbers in the list, I add them in. And that's that's my snowball growing. Here we have a greater thing. And in a way that Brian's going to describe, these things are, maybe this isn't a monoid, maybe it is. Max with numbers is a mathematical structure that you going to identify.

When we're saying separate and recognize them before. We're going to start to recognize mathematical structures. And seeing those structures that make you think, I should be using a reduce here. But in this case, it is a reduce. Let's see, so I'm going to walk through what it would do. Why I am about to type what I'm going to type.

Reduce takes a function that says, given the snowball we've accumulated so far and the next flake it's about to run over and pick up. How do we make the new snowball? And this max, this greater thing. If you'd been rolling over and saying, every number I see. If I see a new number, and I have the current winning number, we combine them to find which is actually higher.

And you keep doing that. So your snowball's really just one number that's getting larger, and larger, and larger if it finds larger things ahead of it. So we can reduce. You see how greater works, by the way? Let's check it out, greater(1,2), greater(2,1). It just gives you the bigger number.

So let's reduce on it.
Joe Nelson: I'm trying to think of the order that they do it. It's the function and the initial value. Is that what it would be in this thing? But wait, if I do this, it's actually going to fail. Can we think of why? We start with zero, and now we're going to start seeing things from the list.

Joe Nelson: Or will it will fail? I'm thinking there could be a problem with negative numbers.
Joe Nelson: Yeah, yeah, yeah, so we have two tests. So it passes the first test. But in the case when we passed in zero for the second test, zero is actually bigger than any of the numbers in the list.

So it de facto wins. It's like before you even started, it's over. So that's why we're talking about the negative infinity thing. If the way we reduce is to find new kings of the hill, new bigger numbers, we want to start with the weakest numbers to be sure that everyone has a chance.

Don't put it an insane contender in to begin with. Negative infinity,
Joe Nelson: See, there you get your satisfaction at the end, All tests pass.
Co-Instructor: We did it. Did we go over Challenge 2?
Joe Nelson: Let's see. I thought so, this is Challenge 2. To triple every number in a list?

Yeah, like using a map and making a triple, and putting them together.
Co-Instructor: I was just busy chatting jokes.
Joe Nelson: I see. I wonder if now is a good time to continue. It hard to feel where everybody is. Is every one here good, thumbs up? That wasn't a lot of thumbs up.

Co-Instructor: Does anybody need a reduce primer? Or does everybody understand reduce? because we're going to look at those with monoids?
Audience 1: It wouldn't hurt.
Co-Instructor: All right, I'm just going to do it quickly. Explicit function that shows the accumulator.
Joe Nelson: Could we make a new thing that reduces something? Let's see, what else could we do?

We could use adding numbers together with reduce. I'm trying to think of another good example.
Co-Instructor: How about concating a list, yeah.
Joe Nelson: Concating a list, okay. Do we have-
Co-Instructor: Make map with reduce.
Joe Nelson: Yeah, I'm trying to think. So we have concat, don't we? We have push, that's kind of though.

Joe Nelson: So how we do it? Our accumulator's got a list going already and wants to put a new thing into that list. So let's think of how we do that. Our function-
Audience 1: Can you clear your screen so you start at the top?
Joe Nelson: Yeah.
Co-Instructor: You might have to refresh.

Joe Nelson: Let me just refresh.
Joe Nelson: Yeah, okay.
Joe Nelson: So the goal,
Joe Nelson: What is our goal? If we have a list, to make another list that's the same? That's kind of a weird goal.
Co-Instructor: Let's just implement map with reduce.
Joe Nelson: Implement map with reduce, okay.
Co-Instructor: Standard tidbit, it reduces a catamorphism or a fold.

Joe Nelson: Undefined, okay. So how this is going to work? We have a list that's coming in. We have a function we should apply to each thing. And we want to build up a new list one at a time with it.
Joe Nelson: So we'll reduce, I see. I'm going to make actually, until I figure out how to do it without using arguments, using it with arguments.

var newmap = function, I'll try it with two. A function that takes what would I like to do to this thing on the list.
Joe Nelson: And inside, we'll return reduce.
Co-Instructor: Can you do a space, or an error, or does it blow up?
Joe Nelson: I think it blows up.

Co-Instructor: All right.
Joe Nelson: I wonder if I should write it in VIM or something or some other place, and then in line and paste it in here. Let's do that.
Joe Nelson: Okay, so we're going to curry this function that takes this, cool.
Joe Nelson: All right, full screen it, oops.

Joe Nelson: So,
Joe Nelson: We're reducing with,
Joe Nelson: Another function, which I think is the composition. Hope this is useful.
Joe Nelson: With the composition of concat and our thing we would like to do, I think. So we have something that's coming in, let's see if it works.
Joe Nelson: And we're starting with an empty list, and we're starting actually with,

Joe Nelson: This looks really iffy.
Co-Instructor: Hey Joe, I don't want to interrupt you, but I have a couple questions once you're done.
Joe Nelson: Actually, let's take the questions. It's a good time right now.
Co-Instructor: Now, okay, Dominic L was asking, does reduce when not passed, shoot, hold on.

I'm typing, everyone.
Co-Instructor: Does reduce when not passed an init value not just start using the first two values in that array? Isn't that how it's like,
Co-Instructor: Array.prototype.reduce works? You have previousVal, nextVal, index and array or something, right.
Audience 2: Yeah, I think I mean, if you want to get down to the, or you can answer that.

But I just wanted to mention that JavaScript's reduce, it gives you more stuff than the normal other language reduce. Like it will pass in indexes in the rest of the array. The main things to focus on is the previousVal and currentVal, I think. That'll get you reduce across any language, like the idea of the fold.

Co-Instructor: Okay, and Mims W was asking that the starting value that we were providing seemed a little weird. Can we explain a little bit more about how initial values should be used with reduce?
Joe Nelson: So let's see, the,
Joe Nelson: Oops.
Co-Instructor: Well, and we're implementing the map in it.

Do you want to try to talk about that?
Joe Nelson: Just trying to find it.
Joe Nelson: Wait, so the one in the exercise or the one we were trying to cobble together?
Co-Instructor: We were implementing map with reduce. And that's pretty clear on how the iterator gets passed, or the accumulator gets passed through.

The seed is just the very first accumulator. So the empty list, I don't know, I feel like following through with that really quickly.
Joe Nelson: I feel like, number one, this is probably incorrect. How does it look to you?
Co-Instructor: I would write a function instead of compose.
Joe Nelson: Okay.

Co-Instructor: It takes its accumulator.
Joe Nelson: What should we call this thing?
Joe Nelson: Add change to something, add new?
Co-Instructor: concatList or something, I don't know. Names, that's why they don't want names.
Joe Nelson: Yeah.
Audience 3: One of the things I'm going to admit to here. When you first were saying you were going to do this, I thought about using the push on the array.

Because I'm JavaScript, which push, and you're going into all these other functions that you obviously know the library. And because okay, if you want to keep adding on to an array through this, basically, make map with the reduce. I was thinking, well, the input's an array and then I'm going to push every element onto it.

Was my initial thought, but you're going beyond that because of your knowledge of the library.
Joe Nelson: Also because even in native JavaScript, there's .concat. What I don't like about push, I like it in many ways, being imperative, I guess.
Audience 3: Yep, yep.
Joe Nelson: But is that if I say [1,2,3].push(4), it returns 4 and not the new array.

And it modifies the original array. So it's this weird changing thing. It doesn't even give you back what it changed. It's really awkward. So if I was going to try and compose that with other things, it would break the string because it's not giving you back the thing in progress.

It just says, great, you pushed 4. It's like, I don't care about 4, I care about this list that's happening.
Co-Instructor: And concat is pure, push is impure. because it mutates the original, yeah.

Ready to take your code to the next level?

Intense courses with world-class teachers and unlimited access to our growing library of videos for the great price of $39 per month.

Get Unlimited Access Now