Last active
May 15, 2018 17:42
-
-
Save kyledinh/bea84842438a297496468a9f4a85b082 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let people = [ | |
{ name: 'Bob', age: 28, child: { name: 'Sally', age: 8, grade: 3 } }, | |
{ name: 'Sara', age: 46, child: { name: 'Lois', age: 14, grade: 9 } }, | |
{ name: 'Ann', age: 27, child: { name: 'George', age: 9, grade: 4 } }, | |
{ name: 'Dave', age: 52, child: { name: 'Hale', age: 17, grade: 11 } }, | |
]; | |
const add1 = (x) => x + 1; | |
const toFieldApplyFunc = (field, fn) => { | |
return (obj) => { | |
let y = fn(obj[field]); | |
obj[field] = y; | |
return obj; | |
} | |
}; | |
const upAge = toFieldApplyFunc('age', add1); | |
const upGrade = toFieldApplyFunc('grade', add1); | |
const addAYear = (x) => { | |
x = upAge(x); | |
x.child = upAge(x.child); | |
x.child = upGrade(x.child); | |
return x; | |
} | |
const getByKey = (key) => (obj) => obj[key]; | |
const composeLTR = (...fns) => (val) => fns.reduce((prev, fn) => fn(prev), val); | |
const createDecender = (fn) => (a, b) => fn(a) < fn(b); | |
const byChildAge = composeLTR(getByKey('child'), getByKey('age')); | |
const descendByChildAge = createDecender(byChildAge); | |
let myPeopleReport = people.filter(p => p.age > 40).map(addAYear).sort(descendByChildAge); | |
console.log(myPeopleReport); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
In most examples I see for functional Javascript, I see simplistic examples of
add1
,time3
andaddSuffix
functions that work on a lone object. I think a more practical example that would show how to use functional patterns is with more practical real-life data: arrays of objects.Let's use this array of objects for our examples:
Modify
If we wanted to add a year to each person, we could write an
add1
function that would be applied to increase theage
field. We could compose it with anupAge
function that will look for field labeledage
and then add 1 to it.This produces an increase in the parent's age, but of course we ask "What about the children?" We can now compose more functions and expand the map method. We will increase their age and grade by a year (we are assuming they all passed!)
Sort
To continue our example, we will sort the array of people by age. For
Arrays
in Javascript, there is a.sort()
method we can chain to other methods called by the array. Thesort()
method take a function that compares two elements in the array. While we are at it, we will refactor themap()
method too, to make it easier to read.Now, let's try to sort by the grade level of the children. To create a sort function by the grade field, we have to compose a function that can look inside the child objects, then use those values in our compare function for the sort.
getByKey()
is a function that will fetch us the value for a specified key. The first time we call itgetByKey('child')
it will return the child object. We will need to curry that output togetByKey('age')
to get the age value. We will combine both functions to ourbyChildAge()
function with ourcomposeLTR()
function.The
composeLTR()
function will take any number functions as parameters, then apply them 'Left To Right'. In other languages and libraries, this is also called apipe()
function,flow()
function orandThen
function. In a pure functional concept, it's the reverse order ofcompose()
.With the functions we created, we can create the
descendByChildAge()
function that can be used by thesort()
method. The function will sort the array by the children's age in descending order, oldest to youngest.Let's add a filter, now our script will report of all people over 40 and what there age and children's age and grade will look like a year from now.
Gets this output: