Transcript from the "Exercise 12" Lesson
>> Jafar: I want to talk to you a little bit about exercise 12. Because exercise 12 you're gonna make the first mental leap, first really important mental leap, in order to get really, really good at asynchronous programming. So, first thing I want you to call your attention to is that this is not allowed.
[00:00:16] When you fill out exercise 12, you're not allowed to pull a value out of an array synchronously like this. Why would I put that kind of restriction on you?
>> Speaker 2: [INAUDIBLE]
>> Jafar: Sorry?
>> Speaker 2: Cuz we're learning asynchronous.
>> Jafar: Cuz we're learning asynchronous programming we're gonna limit ourselves to only those operations, which will work not just on an array but also on an observable as well.
[00:00:37] So go ahead, read that catch question very carefully and give it a shot. And let me know once you pass exercise 12. Yes, question?
>> Speaker 3: There was a quick question on, just the order in doing things. Needed a map then a concat and then a map again?
>> Jafar: Which would totally because first he's using map to turn it into an array of arrays cuz all he's returning is the, is the video.
[00:01:00] So the first time what he's, what he's saying is that he did this. Which, which I wanna point out will work, right? At the same time as you're returning the videos, which turns into an array of arrays. You can also map that and just return the IDs, right?
>> Speaker 3: I'm just wondering if it's less effective though
>> Jafar: But it is less efficient probably, I'm not 100% sure but less efficient enough and the idea it, was actually in this particular case. Yes, it's almost certainly less efficient with the rays because every single map operation start the beginning and then traverses all the way down and so, if you're you're already going over the array, be good to sort of do the transfer.
[00:01:43] I'm not a 100% sure in this case. If you're doing any filtering, certainly, you wanna move filter operations up as early as possible because then all subsequent operations don't need to process those items that you were eventually going to filter out anyways. So in this particular case, yes, it is probably less efficient because each time you call map, you're also allocating a whole new array.
[00:02:01] [SOUND] How many people got done? It's not surprising. It's hard. I didn't expect any to get that but I do wanna talk you through this process because this is actually gonna be a big mental leap. One of the things that developers are typically not comfortable with, is dealing with nested collections.
[00:02:20] Like our friend over there, the first thing you tried to do was concatAll, so that you could get that two dimensional down to one dimensional collection. Because it is just so much easier to kind of deal with, right? We're not comfortable with multidimensional collections for the most part.
[00:02:31] And that's what we have to become comfortable with in order to do asynchronous programming. That's actually key to really effective asynchronous programming. Being comfortable, basically having nested map statements and effectively building trees all secure in the knowledge that you can use concatAll to flatten it out again. You have to be comfortable doing that.
[00:02:49] So here's what most people do, so let's go over the problem here that we wanna achieve the ID title, and the particular boxer, that's 150 by 200 for every the array for the box at the 250 by 200 for every single video in this array of movie lists.
[00:03:06] Right, so once again, we have an array of movie less each of which contains. So here's our movie list, right? So we have instant queue, and then your new releases. So, that's the outer array of movie list. Each one of which contains an inner array of videos, right?
[00:03:26] So what we need to get is the ID title and box art that's only 150x200 for each one of the videos in there. So, a nice flat array of ID title and 150x200 box art. So, let's try and solve it.
>> Jafar: Well, I'm gonna take the movie list and just like last time, I'm gonna map over them.
[00:03:46] And that's gonna give me an individual movie list, and then I am going to go ahead and return the movie lists titles this time I'm going to map it. Now I've got videos, is it video or titles? Videos
>> Jafar: And I'm gonna return the ID
>> Jafar: Of the video, and return the title of the video.
[00:04:22] And now I need the box art, right? Now, I just need to grab that smallest box art. So, let's just go through the videos box art collections, let's spell box art we want the Earl actually the 150 by 200 box art. So I'm gonna go video., if you look at an actual video object notice that every video object has an array inside of it of potential box arts, okay?
[00:04:48] So what I have to do, is I have to find the box art, that's 150 by 200, right here and I have to pull out its url. So, that shouldn't be too hard. It seems sorta like the map and filter chain example that we did before, right? We're first filtering for a box art that meets this conditions and then we're mapping and pulling out only the url.
[00:05:07] So, let's write that right in line here.
>> Jafar: I'm gonna format this a little bit better, so it's clearer what I'm doing. So first off, filter
>> Jafar: So, I'm looking for the box art with the width of 150, was it? Yeah, and a height of 200.
>> Jafar: And once again, I'm gonna be careful about my formatting because I want to keep things readable.
[00:05:44] Even though we're building one long expression here, it doesn't mean that it can't be readable. And so as soon as I have two verbs on a single noun, I put each on its own line,
>> Jafar: And I'm gonna return just the url. So now that I've narrowed the list of box arts to only the one that has 150 by 200, all I wanna do is pull out this url, right?
[00:06:09] So, think we're pretty much there.
>> Jafar: Show you the right number of parenthesis. Okay.
>> Speaker 3: Others saying, the id.video, id.video.id.title.video.title
>> Jafar: Thank you. Perfect, and now I think if it's anything like the last example all I really have to do is use concatAll, to take this two dimensional collection and flatten it out.
[00:07:28] In order to get the box art, I'm filtering all the box arts in the video and I'm grabbing only the one with the width of a 150 by 200. And then, I'm using map to just pull out its url. So, it feels like we're pretty much done here.
[00:07:42] All I need to do is run it. Well that's a problem, property list.
>> Speaker 2: [INAUDIBLE]
>> Jafar: What's that sir?
>> Speaker 2: You have to concat one more time.
>> Jafar: What, do I? Yeah, I think you're right, I do. But I'll get into that in just a moment, and that's actually kind of what I want to highlight, but I think there's also a syntax error here and specifically here believes is that.
>> Speaker 4: I think you don't need that semicolon after map.
>> Jafar: Do I have, thank you. That was the source of the problem. Now, I've got a missing argument list.
>> Jafar: Bear with me. Into the map function, into the other map function,
>> Jafar: Anybody spot my error here?
>> Jafar: Try and make this a little bit more.
>> Speaker 5: [INAUDIBLE]
>> Jafar: That's correct.
>> Speaker 5: And now that you've still have an array.
>> Jafar: Yep, so what you have hit on what I actually wanted to hit on here, I'm not sure what the syntax errors, won't spend too much time on it. but now that we're sure that isn't the right answer and it's not the right answer my syntax error side because box are disposed to be just a url.
[00:09:31] Notice here, box are supposed to be just the URL these results but it's not how do I know it's not? Well, it's the result of the filter that function, what is a filter return?
>> Jafar: An array. What is map return?
>> Speaker 5: An array.
>> Jafar: Right, so box art is actually going to be an array.
[00:09:49] If this program runs correctly, if I can get it to run correctly, it's actually gonna to be an array of the box art. Does that makes sense? So what we need to do is somehow get the array-ness off of that box art, and the logical thing to do and I think a lot of us would love to just do-
>> Speaker 5: Bracket zero.
>> Jafar: Bracket zero. That very thing that I stubbornly told you you could not do, right? So, what's the answer? What are we really doing when we do this?
>> Jafar: We're binding a variable to an item inside of a collection. What I mean when I say bind, is now whatever's in the first item position in that array, we can now refer to using that variable name, right?
[00:10:33] Well, there's another way that you can do that. If I want to bind a variable to every item in a collection, I can use, [SOUND] I just type it right here even though it's crazy, [SOUND]. What have I done when I do this? I've bound x to every item in a collection, right?
[00:10:53] This is the asynchronous equivalent of this,
>> Jafar: If there are just two ways of doing the same thing. Right now, I can refer inside that function any way, x is every item in that collection and I can do something with it. So what I'm missing, what I'm actually missing, the problem is I'm trying to create this object too soon.
[00:11:13] What you've gotta do, is you've gotta keep using map until you've introduced all, so notice here, I've used map and I've brought these identifier, this variable into scope. Because I've bound video to each of the videos in the movie list collection, but I'm not done yet because I actually need one more binding, I need to bind box art to the one box art inside of that video that has the width the 150 by 200 and the url.
[00:11:42] So what I am gonna do is instead of creating the object so early, which is a rookie move, I'm gonna go video.boxarts. I'm gonna move all of this stuff up here.
>> Jafar: Now I want you to notice, right here inside of this function, that now, I have everything I need to create my result.
[00:12:05] Because I've brought in the box art, which is now bound to this box art object right here, in the scope so that I can refer to it. I'm gonna write out the answer and hopefully will become clear what I did here.
>> Jafar: So, now I'm ready cuz I've got everything I need.
[00:12:29] I've got video up here in the closure. I've got box art up here in the closure.
>> Jafar: The title.
>> Jafar: So through the magic of closure scope, I brought in all the data that I need. Now, that can kind of get a little complicated. I mean, how many levels deep am I now?
[00:13:03] How many levels deep is this collection?
>> Jafar: For every movieList we're returning a collection-
>> Speaker 5: Four levels.
>> Jafar: Four levels? I hear four, anybody got anything else? I feel like an auctioneer up here. Anybody got two?
>> Speaker 5: [LAUGH]
>> Jafar: Three?
>> Speaker 5: Three, I guess.
>> Jafar: It's three. It's three, because for every movieList, I'm returning a collection.
[00:13:30] But for each one of those videos, I'm returning another collection. So, I have three levels deep of collection here. Which isn't crazy because I started with a three dimensional collection, right? We nested our maps until we got another three dimensional collection. So now all I need to do is, I need to go from this three dimensional collection down to a one dimensional collection.
[00:13:53] So the point is, we shouldn't be afraid of getting ourselves into a deeply nested collection. It's oka, because we can always fall back on our flattening operators to flatten it back out no one dimensional collection. So if I, see me a get my brackets right. If I do this, I've now taken the two dimensional collection and I flatten it into a one dimensional question.
>> Jafar: I'm actually gonna change my formatting as I go. Because as soon as I add two operators to a single object, I each put them on their own line. And the same thing applies, now I flatten it to a two dimensional collection.
>> Jafar: And we're down to a one dimensional collection, some have run this, hopefully it works.
[00:14:46] Still missing that are for the argument that some of the mistype something some or some of the cheat and show answer but I sure to look very much like this. Except with long functions unfortunately.
>> Jafar: So I mapped over all the movieLists that I'm up, over all the videos within that movieList.
[00:15:10] For each one of those videos, I map over the box arts. Well, first I filter them for only the ones with with the 150. It should have a 200 check there also and then I map it. Now, that I've got all the information I need introduced by the closure scope, I'm ready to create my result.
[00:15:25] And that's what you have to do. You have to keep mapping until you have a variable bound to every value you need to create your result. And once you got to that point, amounts easy. You just have to figure out how deep you are and apply n minus one concatAll.
[00:15:40] So, I've created a three dimension deep collection. So, I just need two concatAll's to flatten it out again. So keep mapping until everything you need is introduced, is down to a variable by a closure. Create your result and figure out how deep you are and then flatten by n minus one.
[00:15:56] So, you're gonna be doing this all over the place. Yep.
>> Speaker 6: So, could you create out of the pyramid structure with this if you kept going?
>> Jafar: Definitely. You will create a pyramid structure. Does anybody think that's a bad thing?
>> Speaker 7: What's a pyramid structure?
>> Jafar: A pyramid structure is what he's pointing out here which is that you see that the code kind of goes like this.
[00:16:13] Right, it goes like that. Anybody ever heard the expression pyramid of doom? We have one person there. If you've done any node programming, you very often end up with this type of nested callback, is a node in order to do one thing after another thing, you have to nested inside of call backs and you end up with what some node programmers call the pyramid of doom.
[00:16:32] This nesting is not a problem but it's really actually nothing wrong or bad about this nesting. One of the problems with Node JS when you do this nesting, is that because they don't have observable and they don't use promises and they just use callbacks. One of the real problems with the pyramid of doom, is that you have to manually handle errors.
[00:16:47] You have to manually forward errors up yourself. And so that's why pyramid of doom is very damaging in Node JS. Because if you can be like seven levels of callback deep and something goes wrong and you can actually correctly clean about yourself, you are a much smarter developer than I am.
[00:17:01] Observable will automatically forward errors for you, if an error occurs anywhere in here arrays, we can count on throw automatically doing it for us. But in the world of observed with asynchronous programming, observable will forward on any errors in any of these observable inner observables up to the top so that you can catch them in one place just like try catch.
[00:17:19] And so you shouldn't be afraid of nesting, the key is not to avoid nesting. The key is to get really good with your code formatting, so that you can make sure that your code stays readable even at multiple levels of nesting. I mean you've probably nested three for loops, right?
[00:17:33] That's not a terribly crazy idea. Very often you don't see yourself more than three or four levels nested. So if you can nest three for loops, you've got exactly the same number of scopes here as if we nested three MFs.
>> Jafar: So, that's the key to solving the next x number of exercises.
[00:17:53] It's always the same thing. Keep nesting map expressions until you have a variable bound to everything you need to create your result. When you've got a variable bound to everything you need to create your result, you know you can stop, return that result. And then figure out how deep you are apply n minus one concatAlls and you're good.