Of Callbacks and Onions

I already mentioned that we’re going through LearnYouNode at PCS. The problems have been pretty good by and large, butone of them stands out for the time it took me to wrap my head around it: number six, titled Make It Modular. The problem is based on a previous problem, in which you have to build something that will take in strings representing a file path and a file extension, and then log to the console a list of all the files with that extension at that file path. Reasonable enough! Problem five was a good learning exercise; I was able to finish it up in what seemed like a not too unreasonable amount of time. Problem six, though.… (spoilers for LearnYouNode problems below, watch out!)

So, here’s my solution to problem five (complete with leftover commented out console.log to help me figure out what it’s doing):

You can see that it pretty much does what it says on the tin: takes in two arguments (process.argv[2]and [3]), treats one as a path and one as an extension, goes to the named path, and logs the name of any file that matches the extension. Easy! Well, once you know how it works, anyway. The same goes for problem number six, which is to take your code from problem number five and turn it into a module, meaning that you now have two files. One is a module that will take the path and extension and a callback function and create an array of all the matches. The other is the callback function that does the logging, as well as the initial call to the module.

The biggest headache I dealt with in problem 5 was that the local variable pathToFile was one that I originally just named path, which of course shadowed the global variable path that I was using to access the path module.

Despite the fact that I already had this working just fine in problem five and just needed to make a tweak to the organization of the whole thing, this took me a long time to figure out. Like, hours. Many of them. One of the big problems I had was that I wanted to pass in the name of a function to my fs.readdir, as I did on line 16 in problem 5 above, rather than just doing it as an anonymous function. This wasn’t simply a preference for me; I wasn’t even thinking about anonymous functions at all for a long time—it always just seems neater and cleaner to me if there are names on everything, so I tend not to use anonymous functions that much.

So there I was, trying to figure out how to have a call to a log function inside fs.readdir when I would need log to also have access to the local variables for things like the name of the callback and all the rest. I moved stuff around for ages, putting function calls inside other function calls and above and below other things. It felt very much like I needed to have functions inside the functions they contained, which was when I remembered an image from The Last Battle, a book I haven’t read in decades. CS Lewis has Tumnus the fawn describe the universe of Narnia to Lucy:

“I see,” she said. “This is still Narnia, and more real and more beautiful than the Narnia down below, just as it was more real and more beautiful than the Narnia outside the stable door! I see … world within world, Narnia within Narnia.…”

“Yes,” said Mr. Tumnus, “like an onion: except that as you continue to go in and in, each circle is larger than the last.”

Which kind of made my brain explode a little. So I walked away from the problem for a while, got some sleep, and the next day looked over some other resources, which is when I noticed that anonymous functions seemed to be the way to go in node. Suddenly my onion collapsed back into itself and everything made sense, so I was able to produce a module:

and a call to that module:

Woot!

Leave a Reply

Your email address will not be published. Required fields are marked *