I believe I have learned some/many/most of the basic concepts underlying functional programming in JavaScript. However, I have trouble specifically _reading_ functional code, even code I've written, and wonder if anyone can give me any pointers, tips, best practices, terminology, etc. that can help.
Take the code below. I wrote this code. It aims to assign a percent similarity between two objects, between say `{a:1, b:2, c:3, d:3}` and `{a:1, b:1, e:2, f:2, g:3, h:5}`. I produced the code in response to [this question on Stack Overflow](http://stackoverflow.com/q/42163299/5218951). Because I wasn't sure exactly what kind of percent similarity the poster was asking about, I provided four different kinds:
* the percent of the keys in the 1st object that can be found in the 2nd,
* the percent of the values in the 1st object that can be found in the 2nd, including duplicates,
* the percent of the values in the 1st object that can be found in the 2nd, with no duplicates allowed, and
* the percent of {key:value} pairs in the 1st object that can be found in the 2nd object.
I started off with reasonably imperative code, but quickly realized that this was a problem well suited for functional programming. In particular, I realized that if I could extract out a function or three for each of the above four strategies that defined the type of feature I was seeking to compare (e.g. the keys, or the values, etc.), then I might be able to reduce (pardon the play on words) the rest of the code into repeatable units. You know, keeping it DRY. So I switched to functional programming. I'm pretty proud of the result, I think it's reasonably elegant, and I think I understand what I did quite well.
However, even having written the code myself and understanding every part of it during construction, when I now look back on it, I continue to be more than a little baffled at both how to read any particular half-line, as well as how to "grok" what any particular half-line of code is actually doing. I find myself making mental arrows to connect different parts that quickly degrade into a mess of spaghetti.
So, can anyone tell me how to "read" some of the more convoluted bits of code in a way that is both concise and that contributes to my understanding of what I'm reading? I guess the parts that get me the most are those that have several fat arrows in a row and/or parts that have several parentheses in a row. Again, at their core, I can eventually figure out the logic, but (I hope) there is a better way to go about quickly and clearly and directly "taking in" a line of functional JavaScript programming.
Feel free to use any line of code from below, or even other examples. However, if you want some initial suggestions from me, here are a few. Start with a reasonably simple one. From near the end of the code, there's this that is passed as a parameter to a function: `obj => key => obj[key]`. How does one read and understand that? A longer example is one full function from near the start: `const getXs = (obj, getX) => Object.keys(obj).map(key => getX(obj)(key));`. The last `map` part gets me in particular.
Please note, at this point in time I'm _not_ looking for references to Haskell or symbolic abstract notation or the fundamentals of currying, etc. What I _am_ looking for is English sentences that I can silently mouth while looking at a line of code. If you have references that specifically address exactly that, great, but I'm also not looking for answers that say I should go read some basic textbooks. I've done that and I get (at least a significant amount of) the logic. Also note, I don't need exhaustive answers (although such attempts would be welcome): Even short answers that provide an elegant way of reading a single particular line of otherwise troublesome code would be appreciated.
I suppose a part of this question is: _Can_ I even read functional code linearly, you know, left-to-right and top-to-bottom? Or is one pretty much forced to create a mental picture of spaghetti-like wiring on the page of code that is decidedly _not_ linear? And if one _must_ do that, we still have to read the code, so how do we take linear text and wire up the spaghetti?
Any tips would be appreciated.
const obj1 = { a:1, b:2, c:3, d:3 };
const obj2 = { a:1, b:1, e:2, f:2, g:3, h:5 };
// x or X is key or value or key/value pair
const getXs = (obj, getX) =>
Object.keys(obj).map(key => getX(obj)(key));
const getPctSameXs = (getX, filter = vals => vals) =>
(objA, objB) =>
filter(getXs(objB, getX))
.reduce(
(numSame, x) =>
getXs(objA, getX).indexOf(x) > -1 ? numSame + 1 : numSame,
0
) / Object.keys(objA).length * 100;
const pctSameKeys = getPctSameXs(obj => key => key);
const pctSameValsDups = getPctSameXs(obj => key => obj[key]);
const pctSameValsNoDups = getPctSameXs(obj => key => obj[key], vals => [...new Set(vals)]);
const pctSameProps = getPctSameXs(obj => key => JSON.stringify( {[key]: obj[key]} ));
console.log('obj1:', JSON.stringify(obj1));
console.log('obj2:', JSON.stringify(obj2));
console.log('% same keys: ', pctSameKeys (obj1, obj2));
console.log('% same values, incl duplicates:', pctSameValsDups (obj1, obj2));
console.log('% same values, no duplicates: ', pctSameValsNoDups(obj1, obj2));
console.log('% same properties (k/v pairs): ', pctSameProps (obj1, obj2));
// output:
// obj1: {"a":1,"b":2,"c":3,"d":3}
// obj2: {"a":1,"b":1,"e":2,"f":2,"g":3,"h":5}
// % same keys: 50
// % same values, incl duplicates: 125
// % same values, no duplicates: 75
// % same properties (k/v pairs): 25