Sunday, August 30, 2015

Eloquent Javascript Chapter 6

Hello people! :) *cheesy smile*

Today I was working through Eloquent Javascript, which you can read for free and work through for free online here http://eloquentjavascript.net, which is a super awesome book teaching programming concepts and Javascript. 

It can get pretty damn confusing tho, although I was breezing through it until I hit Chapter 6.
I am going to write a post tomorrow or later tonight(not likely) explaining everything so anyone can understand it.
It was sooo randomly difficult and unexplained that it really pissed me off.
I can understand it, but it is unnecessary to make it so.. non-intuitively presented.
It is much harder to look at someone else's code in little isolated bits without any context and without any of the knowledge that went into the brainstorming behind the code being looked at.

Yup, case-in-point, here is an excerpt from my notes as I was trying to figure everything out:

  "/* OKAY
     so this is GOD AWFULLY CONFUSING AS SHIT
     But this is what it means:
     It maps each slot in the 0th index of the rows array to the minWidth of all the columns of that index [...]"

I don't want to ^give the whole quote out of context, plus I just wanted to show just how frustrating it was lol. I mean look at that colorful language xD

I am going to be breaking Chapter 6 down into bite-sized manageable bits so anyone can understand it.
There was one particular thing that was bothering me, which I finally figured out.
I will go over that too, but I'll mention it now in case it is throwing anyone else for a loop. (no pun intended LOL)


So we have the following code written by the author(with the example Rows object for context):

/*
0:    [
0:    TextCell{text: ["##"]}
1:    TextCell{text: ["  "]}
2:    TextCell{text: ["##"]}
3:    TextCell{text: ["  "]}
4:    TextCell{text: ["##"]}
]
1:    [
0:    TextCell{text: ["  "]}
1:    TextCell{text: ["##"]}
2:    TextCell{text: ["  "]}
3:    TextCell{text: ["##"]}
4:    TextCell{text: ["  "]}
]
2:    [
0:    TextCell{text: ["##"]}
1:    TextCell{text: ["  "]}
2:    TextCell{text: ["##"]}
3:    TextCell{text: ["  "]}
4:    TextCell{text: ["##"]}
]
3:    [
0:    TextCell{text: ["  "]}
1:    TextCell{text: ["##"]}
2:    TextCell{text: ["  "]}
3:    TextCell{text: ["##"]}
4:    TextCell{text: ["  "]}
] */

function rowHeights(rows) {
  return rows.map(function(row) {
    return row.reduce(function(max, cell) {
      return Math.max(max, cell.minHeight());
    }, 0);
  });
}

function colWidths(rows) {
 return rows[0].map(function(_, i) { //rowZero.map( function(element, index) {
   
    return rows.reduce(function(max, row) { //reduce each row into a minWidth for that row
      return Math.max(max, row[i].minWidth());
    }, 0);
  });
}


So, if you look, you'll see (inside function rowHeight)
row.reduce(function(max,row){
   return Math.max(max, cell.minHeight());
}, 0)

Now, if you are me, you think.. okay, "row" contains "cell"s, so it contains TextCell objects.
and "reduce" takes the first object, compares it to the second, and returns whatever it feels like, replacing them both with something else, until there is only 1 survivor left.

Thus, when I saw Math.max(max, cell.minHeight())
I assumed max would be an object of type TextCell, and that cell.minHeight() would, of course, resolve into a number (integer).
But if max is an object, then Math.max should fail miserably and return NaN.
So why does it work?!

When I finally figured it out, it made so much sense.
The trick is the second parameter to reduce, which is an argument you can use as the first argument to compare against the arrays contents, instead of using the array's contents as the starting point.

So , when we say
row.reduce(function(max, current){}, 0)
This means that 0 will be put in first for max, and current will be the 1st object in the array
Thus, Math.max(max, current.minHeight()); will never be NaN
because the first time it is Math.max(0, current.minHeight());
then every time after it becomes
Math.max(oldResult(which is a number), current.minHeight()(which is the next thing in the array));

I hope this (awfully formatted) quick post helps someone.
If you have any questions, don't hesitate to reach out. :)

~James