This course has been updated! We now recommend you take the Hardcore Functional Programming in JavaScript, v2 course.
Transcript from the "Object Map" Lesson
[00:00:00]
>> [MUSIC]
[00:00:04]
>> Brian Lonsdorf: This is idea of map that if you map over the container, you'll basically grab its value and pass it to the function. See we've got, let me, I like this, how do you, yeah, this s here is our flamethrower. See that? It pulls out the flamethrower and gives it to the function and now we can capitalize cuz this s is just a string.
[00:00:35] So what we've done is opened up our container and given its value to the function. Then it closes it back up. So let's look at that for a minute and think it over. Does anybody have any questions or are you kind of confused? Let's think about that.
>> Brian Lonsdorf: [LAUGH] You look really upset with that.
[00:00:58] [LAUGH]
>> Speaker 2: I guess the problem is it's mixing concept, because there's object-oriented that we have to use because that's what JavaScript is underneath, right?
>> Brian Lonsdorf: Sure.
>> Speaker 2: And then somehow we're making a functional,
>> Brian Lonsdorf: Just hang on to that. I'm just calling it the the same thing. We'll get to it, we'll trace, but the idea is that, don't think of it as an object.
[00:01:29] Think of it as a container for our string, and when we map over our container the string goes into the function we're mapping over. We're just opening up our container, giving its value to the function and so within that function I've got my string, it's there and I can capitalize it.
[00:01:46] And then when we're done mapping it goes back into the container. We're gonna look at another example to probably clear this up. Yeah, I should mention that, you don't need to write a full function. I just wanted to do that to show you like it'll just populate, pass it right into the capitalize.
[00:01:59]
>> Speaker 3: Hey, Brian, there was a question if this is preferable to using valueOf in your container object?
>> Brian Lonsdorf: ValueOf, is a hack on JavaScript that you can use to do some crazy stuff. But what I'm doing is I'm actually assigning a property to my object and it's gonna make the implementations easier.
[00:02:23] But if you guys want to experiment, I actually mentioned like nobody is doing this right now. Get out there and play with it, get crazy cuz maybe valueOf will be the solution that we've all been looking for. [LAUGH] So, we're just using val as a convention. But look at the implementation of map real quick and see I have to grab this.val.
[00:02:45] And that actually is, if you look at map and you look at what's happening, we're literally running the function on the value inside the container. That's what map is doing, it's running the function that's given to it on the value inside the container. It's like it's saying what it's doing.
[00:03:03] We're gonna get more into the intuition in what we're doing here. But yeah, play around with valueOf, that's my answer. [LAUGH]
>> Speaker 2: So is the reason that we're doing this container so that we can add functions into the prototype? The map for example.
>> Brian Lonsdorf: We will, that's exactly right.
[00:03:20]
>> Speaker 2: That's one of the things we're trying to get to.
>> Brian Lonsdorf: That's how we're going to get dynamic dispatch.
>> Speaker 2: Okay.
>> Brian Lonsdorf: So this concept isn't foreign, right? Everybody knows how to map over an array. We were all just doing that, we have our container of three, we map over it and add one.
[00:03:37] Or I shouldn't say container, we have an array of three, we're mapping add one over it. We've got a container of three we're mapping add one over it. Now, most people think of map and they're like, iteration over a collection, for loop, I got what map does. That's just a specific implementation of map on an array.
[00:03:55] We're gonna get into the general idea of map that works on anything, and that container is just like a singleton array, it's got a value in it. And we're gonna map a function over it. Are you guys good with me? Who's with me? [LAUGH] All right, stick with it.
[00:04:15] I'll show you why we're doing this. But right now, you're still probably just like, that's stupid. [LAUGH] All right, so, yeah, the true idea is you go inside an object and you run a function from within the object. So we saw that function run inside the container. This is Joe's slide, it's so cool.
[00:04:34] [LAUGH] Anyway, we go into our container. One thing that's important to note about this is, is we've got, there's a lot going on in the slide and we'll talk about. The top line here, we have our container of one, two, three. We're gonna map reverse over it and then map first over that, right?
[00:04:56] So what we're gonna do is basically, when this goes into reverse, we get a reversed list. Oops, we get a reversed list. And then when we map over that reversed list and grab first, we get the value of three. It's changing types inside the container. It cannot have a type that is like, it's this container takes strings.
[00:05:21] Doesn't work. This container has to take any value if it's gonna be mapped over. Notice how that's composition? Is that weird? That top line, left or right composition, that's what we all wanted, right? [LAUGH] And there's actually laws that enforce that, that is composition. There's some weird like theory behind this stuff that we're gonna get into.
[00:05:44] But that's string that we can map, and that's composition. Underneath that, we're gonna get the length of the flamethrower and then add one to the length, so we get 13. So, it changed from a string to a number, and then we added one to it. The top one changed from and array to another array and we grabbed the first one.
[00:06:02] So, you can chain maps and the reason you can chain maps is because it keeps putting it back in the container after you map, right? Like if I map reverse over one, two, three, I will get a container of three, two, one. And if I map first over the container of three, two, one, I'll get a container of three.
[00:06:20] It just keeps putting it back into the container, so you can keep mapping. It's kinda like when people return this, so you can keep chaining. It's like, it's that, but in a more functional sense cuz we're making copies we're not just returning this. That's something else I should mention, we're making copies of container along the way.
[00:06:36] You could probably optimize, but I'm not doing that, but I'm gonna be immutable. All right, so, we're gonna spend a lot of time on functors, cuz you guys got to understand them or else you're gonna not understand monads or applicatives. So it is a larger ghost. [SOUND] Sorry, I'm trying to like, I'm getting distracted by the chat, maybe I should turn this down.
[00:07:01] [LAUGH] So what was the slide about? Yeah, I just wanted point out, so like we saw before, we've got this map that takes its function and its argument and we've got the map that we call dot on, that's why we're not using underscore dot map, the bottom one, all it's doing is turning around and calling .map for us.
[00:07:28] So the main difference here, these do exactly the same thing, these two maps. But the main difference is this one needs to exist. This Container(3) needs to exist so I can call .map on it. This Container(3) doesn't need to, I could just partially apply this map without one.
[00:07:45] Just like we've been partially applying things and currying things, the same difference whatever. Scott would get mad at me for that. [LAUGH] But the idea is that all we're gonna do is to find a map that we can just call dot on under the hood. Does everybody see that?
[00:08:01] It's second argument we are just calling .map on it. This is gonna be a pattern too, just throughout, like if you ever wanna make something more functional and point free and composable, just take it's object last and call dot under it, under the hood.
>> Speaker 2: Did you say that the container didn't need to exist in that second part?
[00:08:20]
>> Brian Lonsdorf: And the second line is partially upon that cuz it's curry. So, I don't need a container for it, it just be map by one. And the top one, what do I call dot on? I don't have the container, I can't call dot on anything.
>> Speaker 2: But when you _curry function, you need something that has a map function in the prototype?
[00:08:39]
>> Brian Lonsdorf: I'm sorry, what I meant to say is the map since is curry, I can just give it map add and I can partially apply it without that second argument, but the top one it needs its.
>> Speaker 2: Okay.
>> Brian Lonsdorf: And then that way, you can build for like machines of just composing functions and stuff without getting our data first.
[00:09:02]
>> Brian Lonsdorf: All right, so here's some examples of our new map, I just took the dot and now we're just using the normal map we've always been using in this class but we're now using the underscore dot just, and we're gonna call like, all right, what if our container matches cat?
[00:09:18] We can't just call match on catsup. We have to map that over it, right? Because it's inside the container. Match does not work with the container, it works with the string inside the container, so we map over it. Just like if catsup was in a list or an array and we wanted to map that match function over the array, you can't just give an array to match, you have to give the strings inside the array.
[00:09:40] So, you're basically mapping this function over the value inside the container. So, let me know if how you guys are feeling about this, cuz you have to do exercises in a minute and I'm gonna be like, I'm not helping. [LAUGH] Compose underneath is just going to reverse dog and grab the first, so we'll get the g.
[00:10:02] That's my favorite example of reversing first to get last. So there's just a way to use map and we could have just called the dot syntax. But this is kinda more composable in our point free way here.