This weekend I wanted to refresh what I knew about Functional Programming. I read and took some notes about it, (feel free to add your thoughts in the comments section):
The theory:
There are some principles in regards of FP:
- FP uses Pure Functions: Functions that its return depends on its input, for example:
- Math.floor(16) --> 4 // This function will always return 4 when it's called with 16
- Math.square(2) --> 4 // Same for this function
- To contrast Impure functions:
- function() { return x; } // In this case this function will return the value of X but doesn't depend on any input, and will depend on X mutation
-
Do one thing well:
- Functions that are divided into smaller functions, that are divided into smaller functions until the smallest function does one thing but does it well
- Small testing, since the functions are really small it's easy to keep them tested, rather than trying to test really big functions
-
Immutable data/state, each function should return a new object. Those object data structures are: [] or {}, Arrays or Maps
- In terms or performance it's not affected because the compiler most likely knows that non changed values will have the same hash (not get to deep into this)
- Using immutable data reduces bugs because the new object is the result of your called function, making easy to have different states across time for your data, for example:
- emptyCar = createCar();
- carWithOneBook = addBookToCar(emptyCar, myBook)
- carWithTwoBooks = addBookToCar(carWithOneBook, myOtherBook)
- In the previous example it's easy to do time travel because your objects are independent one to the other, so you know that if the addBookToCar works well, it'll work well in all the cases, plus testing that function will be easy as well.
The practice
A while ago I was in a phone interview, the interview was split in two sections: Technical questions + Coding Challenge. I solved the challenge applying what I learned from this FP weekend.
Coding Challenge
Part 1:
Given an object with the keys in kebab-case, convert the keys into camelCase.
Part 2:
Do it for nested objects.
Sample object:
const userData = {
"first-name": "John",
"last-name": "rough",
"social-security-number": 9083910,
"pets-details": {
"cats-details": {
"how-many-cats-are": 3,
"cat-data": [
{
name: "Charlie",
age: "8 months",
"hair-color": "red"
},
{
name: "Angel",
age: "2 years",
"hair-color": "white"
}
]
}
}
};
I divided the problem into two. First...
Convert a string from kebab to camelCase, the functions created below are returning a new object, are simple, and do one thing well:
// Create a function to split a word into arrays by a char
const splitStringByChar = (key, char) => key.split(char)
// Create a function to capitalize an array of strings
const capitalizeArray = stringsArray =>
stringsArray.map(key => key[0].toUpperCase() + key.substring(1, key.length))
// Create a function to join an array
const joinArray = stringArray => stringArray.join("")
// Create a function to lowerCase the first letter of a string
const lowerCaseFirstLetter = key => key[0].toLowerCase() + key.substring(1, key.length)
// Now run it altogether
const camelCaseString = toCamelCase => {
const splittedKey = splitStringByChar(toCamelCase, "-")
const capitalizedArray = capitalizeArray(splittedKey)
const joinedKeys = joinArray(capitalizedArray)
const lowerCasedFirstLetter = lowerCaseFirstLetter(joinedKeys)
return lowerCasedFirstLetter
}
And second... a function to convert the object to camelCase:
// Create a function to convert the object to camelCase
const convertToCamelCasedObject = obj => {
// Create the new object to be returned
let camelCasedObj = {};
Object.keys(obj).map(key => {
const newKey = camelCaseString(key)
// Checking if the object is an object and needs to be converted as well
if (typeof obj[key] === "object") {
camelCasedObj[newKey] = convertToCamelCasedObject(obj[key]);
} else {
// Pointing the value to the new object[key]
camelCasedObj[newKey] = obj[key];
}
return camelCasedObj;
});
return camelCasedObj;
};
Conclusion
FP is good to change the way that you think or solve problems, by design it's good for Distributed Systems.
What would you change to make it better/simpler? What would you add about FP?
Thanks for reading!
Top comments (7)
Sorry to point out but writing small - small functions is not all together functional. You can try lodash
flow
to composecamelCaseString
using those small functions, that would be functional approach -> , "Composition".Hi Pradosh - Good to know about lodash and flow, I wasn’t familiar with those! However, in this case as it was an interview challenge I wasn’t allowed to use any third party utility methods, but to solve it by myself. 😅
Oh Okay, you know you can implement something like flow, this is just POC and not tested either
This is really cool! Thanks for sharing! 💪🏽💪🏽
Now I see what you meant following the book that Bryce suggested below: mostly-adequate.gitbooks.io/mostly...
Thanks Pradosh!
Hey Adán, I think this is a good intro into FP! One resource that I really like that covers more advanced topics is: mostly-adequate.gitbooks.io/mostly...
Hey Bryce - This looks great! Thanks a lot for sharing! Definitely helps to improve my skills! 💪🏽 Appreciate it!