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

In this exercise, you will use _.add and _.map to make a function that increments a value inside a functor. Brian does this exercise with the audience to help get them started writing functors.
- Problem: http://jsbin.com/yumog
- Solution: http://jsbin.com/xiwofojura

Brian Lonsdorf: I lied, container's actually called identity. So, we're going to look at identity here and just pretend it's container, okay? Same thing, different name. Okay, so let's do exercise one together. I run mine a little bit differently, but same idea. We've got our test down here that's going to run our example and pass or not.

So we have to define how how to, yeah, yeah, we're going to use add and map to make a function that increments a value inside a functor. Does anybody want to give me some help? Does anybody kind of get this stuff?
Brian Lonsdorf: All right, let's try it. Okay, so, and I strongly encourage you to just open this up and just start playing with it, start wailing on it.

Like over here, I could say, what if I have Identity of 3? It's this big gross thing, all right. Let me do toString on it, so it looks nice. We have an Identity of 3, literally. How do I add 1 to that? I can't do add 1 with Identity of 3, right?

That's not going to work. Because add is not defined. Now I get, 1Identity(3), that doesn't work. I want to add 1 inside the Identity. We learned about this map function a minute ago. So that's probably what it's going to be. Does anybody want to give me a little help at this point?

Brian Lonsdorf: Okay, we'll keep going. I want us to understand this, so don't let me go on until we get this, all right? Somebody's asking what pointfree and JS Bin is. Pointfree is a library that implements the fantasy-land spec that we'll talk about later, but in a pointfree way.

Hey, hey, Valentine's has got it. So, am I saying your name right? Like the saint, right? So we want to map(_.add(1)) over Identity of whatever, I'm just writing it here so we can see. So that'll be, see, it looks a little crazy like that, let me do a toString here.

JS Bin outputs the whole thing for some reason. If you did it in the console, it would look a lot nicer. But we're going to get Identity(4). This isn't the solution, I want a function that increments a value inside any functor. Well, there it is, I'm just going to map(_.add(1)) over whatever functor comes in.

So let's try this out, see if it works. Okay, exercise one is okay. So let's talk about that, let's beat it up. Ask me questions, tell me why I'm wrong. Let's talk about it, anybody? You there in the hoodie.
Brian Lonsdorf: He's not a plant.
Off Camera 1: How is it, I thought map took a lot of arguments?

Brian Lonsdorf: Yeah, no, no, it's curried. So we're only giving it one right here, just like add takes more than one arguments, and that's curried. So we're mapping curried with add. Normally we'd do it like, second argument, Identity(2), etc. So that's a great question. We just went over that in part one.

But part of, part of map, part of what everybody is hardwired to think map does is run many times, right? Everybody's like, map will run many times. And it doesn't. If you have an array of one item, it runs once. If you have a container with one thing in it, it runs once.

If you have a maybe with one thing in it, it's going to maybe run that once. So think of it as, map is not about iterating. It's about going inside of a object or a data structure and running a function from within that data structure on its properties or behavior.

Identity will become a little bit clearer later. The main thing to think about right now is just like a neutral functor that you can play with and so you get a feel for map, with no added behavior. So let's do another one, let's see. So I'm going to map this real function, this is a little bit clearer.

So I'm going to get x, and x will be whatever's inside my identity, okay? And I'm going to do x.toUpperCase(), awesome. This is going to be the best. And then I have my identity. Ident, I've lost how to spell identity. Identity, yeah. Of, let's do someString, all right. And, that didn't work.

Gotta return, maybe?
Brian Lonsdorf: Yeah, gotta return. Okay, let's do it over here on the left.
Brian Lonsdorf: Yeah, this is awesome.
Off Camera 1: You should do it.
Brian Lonsdorf: Yeah, I'm just going to do over here and like name it. Do it, thing. All right, so it takes x. In this case, let's make x firehose to commiserate.

And then we'll return x.toUpperCase(). All right. Now we run this. And you know what I'm going to do? I'm going to call toString on thing at the end. Thing, thing isn't, thing is already there, yeah, thing.toString. This, seriously, having a call toString is not common, it's just because we're in JS Bin.

Is this too low on the screen for everybody?
Off Camera 1: Is it too what?
Brian Lonsdorf: Low on the screen to see?
Off Camera 1: It's fine.
Brian Lonsdorf: Okay. So let's try a different one. So x became, let's give ourselves some room here, x became firehose inside the map, and it worked all inside Identity.

So mapping this function over identity of a firehouse. x became the firehose, we uppercased it. And then what we get is Identity with the uppercase FIREHOSE in it, neat. So we ran a function inside of identity. Let's think of another example. Let's do, we'll do our array, why not?

4, 3, 2, 1. And we'll just do reverse on that. The destructive impure reverse. So we'll do our thing.toString. There it is, it reversed it. Are you guys getting a little bit of a feel for it? Are you playing with it? Or are you just staring at it and trying to understand why the hell map is working on the Identity?

Off Camera 2: We're having some confusion in the chat on what thing is, what we're going over with that.
Brian Lonsdorf: I'm sorry. It is our test function we're defining to play with, because this is kind of hard to work in, so I'm going to work over here and then just run it over here.

So it's actually not our test function, to be honest, it's our, there it is, now it's a function. So if I call test function with identity, yech, toString. Okay so, let's see, let me think of one more example here. Because we've gotta, I've gotta let you guys play with this.

I gotta cut you free. You have to fly. Somebody asked, does Identity act as a list within a map call? No it doesn't. There is no array going on here. This is a totally different map than you're used to. So identity is just sitting around something, anything. Let's make it, does anyone know the date, getDay or something like that?

All right, so now we're going to map this over a new date.
Brian Lonsdorf: See if that works.
Brian Lonsdorf: That's weird, what'd I do?
Off Camera 1: Did you run it first?
Brian Lonsdorf: Good old. Wait, no, but it should already have run the map over the identity of the new date. Did I do it wrong?

Maybe I have to re, I see, you've gotta run it to refresh it. toString of undefined. I don't know what the actual date getDay function is, it doesn't matter. The point is that Identity has anything inside it. It could be a date, x becomes the date. It could be a string, x becomes a string, it could be whatever.

Identity is like a list of one thing. So if I have 2, I could make 2 plus 2, right? x becomes 2. Does everybody see that?
Off Camera 2: Hey, Brian, there's a question from James M in chat on whether this, I think he means identity as kind of like a with block in JavaScript or Python.

Brian Lonsdorf: Don't think of that way. You're just going to destroy your brain. I mean, if that's the way that makes sense to you, sort of, but I guess you can see that you're getting the context. It's not going to change this, if that's what you're worried about. We're not going to use this at all, which is pretty great.

Except for in inside the implementations of objects, which you don't have to deal with. Yay, no this! So let's run this and try to do this with a list here, just make sure. Okay, I get a 4 out, because I called toString on it.
Off Camera 3: I got a question, Brian.

Brian Lonsdorf: Yo.
Off Camera 3: Are you showing Identity just because it's the easiest functor? Or is it something that you actually use much compared to maybe?
Brian Lonsdorf: Identity is cool because what it does is allow you lift things into the functor world. Even if you don't want any side effects with it, it can compose with other functors now.

It's kind of the basis of monad transformers. And you end up using it just like id. Like, when you see the id function, you're like, what would I ever use the id function for? And then you actually start doing pointfree code, and you're like, I need that. So yeah, it's just like this neutral functor if you need a functor and you don't want any side effects to satisfy some type signature.

Or let's say some jerk made their function with map around it, without making it, calling map later.