Map from Scratch

23 Mar 2022

3 minute read

"You know what I still don't understand?"

"What?"

"Array.map. For loops were heady enough, I had a tough time getting that concept into my head in the first place. And now a bunch of pedantic FP nerds on the internet keep telling me to drop the for loops and start mapping and reducing. But I don't get it! I wanna stick with my for loops."

"Those same nerds have implored me to start using map and reduce too, but I don't really get it either …"

"… wanna try building it from scratch?"

"What?"

"Wanna try building map from scratch? I did a bunch of DIY projects with my dad growing up, and seeing a thing being built from basic pieces up to the final product really changed my perspective on a lot of things. Stairs, fences, walls, cabinets … I understood a bunch of things much more clearly once I built one myself."

"Interesting idea. So … um, where do we start?"

"Maybe with the return value?"

"Seems sensible. No matter what, we're returning an array at the end, so … let's write a function that returns an array."

CODE:

 
const map =  () => {
    return []
}

return map()

 

RESULT:

 []
 

"What next?"

"Not much use returning just an empty array. Eventually this should return our transformed array."

"But let's take things slow, maybe as a first step, we could just return the input array."

"Alright, this seems kinda dumb, but let's do it."

CODE:

 const map = (arr) => {
    return arr 
}

return map(["what", "a", "dumb", "function"])

 

RESULT:

 [ 'what', 'a', 'dumb', 'function' ]
 

"Cute demo code."

"I know, right? Let's see … we're also going to need a callback function at some point down the line, so if we're going through the weird song and dance of putting the pieces in place like this, then that's the next step."

"Allow me."

CODE:

 const map = (arr, callback) => {
    return [arr, callback()]
}

return map(["demo", "array"], () => "stubby the string returner")

 

RESULT:

 [ [ 'demo', 'array' ], 'stubby the string returner' ]
 

"Yeah! Now you're getting it! Why not act silly when you feel silly."

"But now we have to cross another mental hurdle … we've got our input array, and we've got our callback, and now we actually have to do something with them."

"Hmmm … a puzzler indeed. Well, maybe the callback function can just take in and spit the input array straight back out."

CODE:

 const map = (arr, callback) => {
    return callback(arr)
}

return map(["demo", "array"], (arr) => arr)

 

RESULT:

 [ 'demo', 'array' ]
 

"Alright, this is looking a little better."

"But still not quite right, the callback doesn't work on the array itself, it works on each element in the array."

"You know what, to hell with it. I'm just putting a for loop in there. It's all iteration right? Why not iterate with a tool we already know how to use."

"Yeah, maybe you're right. Just for loop through the thing, push the results into the array, and then return the array."

CODE:

 const map = (arr, callback) => {
  const result = []

  for (let i = 0; i < arr.length; i ++) {
    result.push(callback(arr[i]))
  }

  return result
}

return map(["demo", "array"], x => x.toUpperCase())

 

RESULT:

 [ 'DEMO', 'ARRAY' ]
 

"Wait. We just did it!"

"Really?"

"Yeah, you get identical output to the real map now:"

CODE:

 return ["demo", "array"].map(x => x.toUpperCase())
 

RESULT:

 [ 'DEMO', 'ARRAY' ]
 

"Alright, I guess we just did it right? Same input, same callback, same return value. This is the map function."

"This is leaving me somehow more confused than when we started. What's the point of map? You can see it for yourself, all we wrote was a wrapper around a for loop. If you can get the same result from a for loop, then why does map exist at all?"

"Well, I guess we only had to 'configure' the for loop once, if that makes sense. If you look at the native map function, we never had to tell it where to start iterating, where to stop, how much to increment the iteration by, where to PUT the result of the iteration code. We just gave it a list of stuff and a callback to perform on every item in that list, and it did it's thing."

"Interesting, so you could say it's like a batteries-included looping tool. It already knows the basics of what you're trying to do, so you don't have to do all that setup code yourself."

"Yeah, that's a way to put it. I dunno if I quite understand where to use it now, but I definitely understand what it is a lot better."

"Me too!"

Leave a comment

Related Posts