Check out a free preview of the full The Good Parts of JavaScript and the Web course

The "Function Challenge 5" Lesson is part of the full, The Good Parts of JavaScript and the Web course featured in this preview video. Here's what you'd learn in this lesson:

In this challenge, you will write the collect(), filter(), and concat() functions.


Transcript from the "Function Challenge 5" Lesson

>> [MUSIC]

>> Douglas: Write a collect function that takes a generator and an array and produces a function that will collect the results in the array. So, we're gonna make a generator that works like the NSA. It's going to spy on a function and record everything interesting that that function returns, okay?

First, we'll set up the empty array where collect is gonna keep its stuff, then we'll call collect, passing it any generator and that array, and it will return a generator, which will work exactly like the first generator, except it will record everything that it returns except for undefined.

>> Douglas: So, we can call that generator a few times, and then we can look at what's in the array and it will have captured those values. So, here is collect, collect takes a generator and an array that returns a function that gets the next value from the generator.

If the value is not undefined, it pushes it on to the end of the array in either case it will return the value. So, who got something that works? [LAUGH] So close? Anybody do something interesting?
>> Speaker 2: Can you just return array.push value instead of having the return value outside of the u?

>> Douglas: I don't recall what it is that array.push returns. I think it might be an updated length of the array. Does anyone know?
>> Speaker 3: Yeah, it sounds right.
>> Douglas: Yeah, so unfortunately array.push isn't smart enough to do that. Anybody else, we’re going onto the next one? Write a filter function that takes a generator and a predicate.

A predicate is a function that returns a boolean true or false and produces a generator that produces only the values approved by the predicate. So, in this case, we're going to be filtering using the third function. The third function will return true only if Its argument is divisible by 3, so we'll use that to select factors of 3 from the sequence given by the generator.

So we'll have the fromTo generator going to (0, 5), and the third function, and it will return (0, 3) and then undefined.
>> Speaker 4: So, you're asking, if I call this sequentially, five times, I should only get zero, a three, or an undefined? Those arent the first three results I should get.

>> Douglas: Those are the results.
>> Speaker 4: I call the three times the results yourselves write.
>> Douglas: Okay, let's look at filter, so did everybody figure out they need to use a loop? Yeah, that was a key to this one, so very good. We'll get to that, so here's one way to write filter.

Well, first off, who got something that works? Very good, so filter takes a generator and a predicate and returns a function, which will stay in a loop, calling the generator, until it gets a value which is approved by the predicate. In which case it will drop out in return the value, and that's an acceptable way to do it.

Although in EF6, my most favorite new feature in EF6 is going to be tail recursion, or proper tail calls, which would let us write it like this. We're going to have a recursive function that I'm calling recur, and it will continue to call itself until the predicate becomes true.

So, this is where it calls itself, and the reason why this needs a new feature in the language Is that, in ES6, the compiler is required to optimize that call. So, instead of doing a call and then a return, it will do a jump back to the recur function.

So, this function will run in the same time and same memory pressure as the earlier one. At this point, there will no longer be an advantage to using loops over recursion, and that's great, so I'm really looking forward to that. Anybody else do a third approach or any other?

>> Speaker 3: I think there should be a way to use that [COUGH] pose function that we wrote earlier, calling a function on a function. Well, we're not really calling a function on a function, but it feels like we are.
>> Speaker 4: [INAUDIBLE] because they're so used to Python. You could, if you look back to it.

>> Douglas: Yeah, confused for awhile there. I actually think that we have too many looping statements. If it were just me, it would be a loop, and that would be it. You know, loop bracket, and everything would happen in that. Yeah, because I find, well, I'm not using loops much anymore.

But, when I do, I tend to want to break out of the middle, and we've got a loop syntax, which says will break out of the top, will break out of the bottom, but that's not usually where I'm going. If I'm using a loop that is that discipline, I probably don't need to use a loop at all.

Anybody else? Okay, so shall we go on to another one? Sure, why not? Okay, so let's do one more, this time we're going to concatenate a couple of functions together. So, write a concat function that takes two generators and produces a generator that combines their sequences. So, we're going to call concat, we're going to pass it a generator, which is from (2, 0) to 3, and from (2, 0) to 2, and that will give us a new generator, which will produce the sequence (0, 1), (2, 0), 1, and then undefined.

So, here's concat, it takes two generator functions. It has a variable to remember what the current generator function is. It returns a function which gets a value from the current generator. If a value is not undefined, it returns it. Otherwise it replaces the current generator with the next generator and returns a value from that.

So who got something that works for good. Anyone take a different approach.
>> Speaker 4: [INAUDIBLE] temporary generator.
>> Douglas: Because. Next year, when we have the... thing, then I want to write it this way. Whereas I can take any number of generators, and I'm going to be using the element function that we wrote earlier to help me step through that array of generators, and I'll just Load the next one in.

So that's why, I didn't mean to show off but but that's why.
>> Speaker 2: What are the gens?
>> Speaker 4: Let's see the previous slide.
>> Speaker 4: Layer returning gen instead of value.
>> Douglas: returning the result of calling gen and call easy value as I see value it was G.M. and if it doesn't succeed you're calling it a.

You know she just tends to just get to the next generator. Call it the call that each other pretty tough assignment one changes because it's the first time three cause just one second time three cause your third time three cause you're passing suppose you're one to the fourth time three because Jack money gets under five cents JANDA Gentoo returns a result of Gentoo or we have a OK.

>> Speaker 4: Yet to return to tell you I was expecting to return so That's as well the next stuff.
>> Douglas: Yeah.
>> Speaker 4: You said value equals gen2.
>> Douglas: Right. I couldn't have done that business inside of vf. I could have reversed it.
>> Speaker 4: Okay, I gotcha you now.
>> Douglas: Yeah, right.

You think it would have been clearer doing it that way?
>> Speaker 4: Well, I prefer to have one return than two, I guess.
>> Douglas: I'll think about that.
>> Speaker 2: So, when your next function your
>> Douglas: Then next.
>> Speaker 2: [COUGH] What's element?
>> Douglas: Element is a function we wrote this morning.

>> Speaker 2: Yeah.
>> Douglas: You remember that.
>> Speaker 2: It pops off, it pops off to the next.
>> Douglas: Yeah.
>> Speaker 2: Just pops.
>> Douglas: It returns the next thing from an array.
>> Speaker 2: Not because of pop it.
>> Douglas: You should, we did it twice
>> Speaker 2: Yeah, there it is.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now