- Notifications
You must be signed in to change notification settings - Fork0
Functional Programming in Javascript Tutorial
hemonth/coderoad-functional-school
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
A trip through functional programming in Javascript using common built-in Javascript array methods such asmap
&reduce
.
By the end, you should have an understanding of how to use array methods to manipulate semi-complex data.
Level: IntermediateKeywords: javascript, functionalLength: 1-2 hours
CodeRoad is an open-sourced interactive tutorial platform for the Atom Editor. Learn more atCodeRoad.io.
install the tutorial package
npm install --save coderoad-functional-school
install and run theatom-coderoad plugin
Array -> run a function over each item -> Array
You've filtered and sorted our data, but neither of those actually change the data.
Wouldn't it be simpler if you could just change your grades?
You can use the array methodmap
to run a function that returns changes to your data.
As an example, let's look at how you would increment each number in an array.
functionaddOne(num){returnnum+1;}[1,2,3].map(addOne);//> [2, 3, 4]functionaddToVal(obj){obj.val+=1;returnobj;}[{val:1}].map(addToVal);//> [{ val: 2 }]
map
can change data, and it can also alter structure of the data you're working with.
functionmakeObject(num){return{val:num};}[1,2].map(makeObject);//> [{ val: 1 }, { val: 2 }]
Similarly,map
can also restrict the data you want to work with. See the example below to see another way scores could be sorted.
myBest.map(function(student){returnstudent.score;}).sort().reverse()//> [93, 91, 88, 88, 82, 81, 73]
In this example,map
transformed an object with keys of 'title', 'instructor', 'name', 'score' and 'grade', to an array of just scores. Values weren't changed, but rather limited to a smaller subset of scores.
map
is powerful. Let's see what you can do with it.
Those D & F grades would look a lot better if they suddenly became A's.
Let's go back to before we filtered out the bad grades, and instead change the grades to A's.
Array -> run a function for each item
You've updated your grades, but they're still in an array. It's time to loop over them and log them to the console.
To open the console, go toView >Developer >Toggle Developer Tools. Or presscmd+opt+I on Mac,ctrl+alt+I on Windows.
forEach
has a lot in common withmap
, but there is a big difference. Understanding that difference is important for grasping the difference between:
- functional &imperative programming
- pure &impure functions
Know it or not, you're probably already used to "imperative" programming.
Imperative programming describes the order of actions
Imperative code tells the computer what to do, step by step.
varx=1;// make a variablex=x+1;// add onex=x+1;// add anotherconsole.log(x);//> 3
Functional programming describes the data transformation
Functional programming is a lot like writing math equations. As in math, 1 + 1 always equals 2.
In the same way, apure function will always have the same result from a given input. Input 1 -> output 2. Every time.
// a pure functionfunctionaddOne(x){returnx+1;}addOne(1)//> 2addOne(1)//> 2
A function is "pure" if it doesn't change anything outside of its scope. Pure functions are easy to test, reuse and reason about. In other words, they make your job easier.
On the other hand,impure functions are less predictable. The result may be different if you call it at a later time.
vary=1;// impure functionfunctionincrement(x){y+=x;returny;}increment(1)//> 2increment(1)//> 3
It's good practice to ensure yourmap
functions remain pure.
ButforEach
can be a little more dangerous. Why? Let's have a look.
[1,2,3].map(addOne);//> [2, 3, 4][1,2,3].forEach(addOne);//> undefined
What?undefined
?forEach
runs a function on each item in the array, and doesn't care what the function returns. Functions called byforEach
must make changes, calledside effects, to even be noticed.
// impure function, changes logfunctionaddOneToLog(x){console.log(x);}[1,2,3].forEach(addOneToLog);//> 2//> 3//> 4
Now that we see howforEach
works, let's use it to make calls to theconsole
.
Array -> first element that matches a condition
Somehow your name has disappeared from the computer system. We'll have tofind
a way to get it back.
You quickly put together a list of other students in class. If someone changed your name, it'll be the name that is not in that list.
find
works similar tofilter
, but returns only the first match.
var data = [1, 2, 3, 4, 5, 6];function isEven(num) { return num % 2 === 0;}// returns all matching data to a conditiondata.filter(isEven);//> [2, 4, 6]// returns the first matchdata.find(isEven);//> [2]
Find is great for performantly matching unique values in data, such as an "id", or in our case: a name.
Array + Array -> Array
Before we've been working on a structured set of student data.
// array of students[{"title":"Relational Databases","instructor":"Sean Quentin Lewis","name":"Rebecca Heineman","score":71,"grade":"C"}// students in courses...]
To be safe, let's now work on the original data set. Notice how it is structured differently.
// array of courses[{"title":"Relational Databases","instructor":"Sean Quentin Lewis","students":[{"name":"Rebecca Heineman","score":71,"grade":"C"}// students...]}// courses...]
In this data set, there is an array of students within an array of courses. So how can we recreate our original array of students from the courses?
Weird things happen when you start combining arrays. We can useconcat
to bring sanity.
[1,2]+[3,4];//> "1, 23, 4"[1,2].push([3,4]);//> 3[1,2].join([3,4]);//> "13, 42"[1,2].concat([3,4]);//> [1, 2, 3, 4]
Unfortunately, Javascript is missing a built in array method to concat multiple arrays together: let's call itflatten
(sometimes calledconcatAll
).
flatten
should loop over an array andconcat
each element.
Let's look at an abstraction of what we need to do:
varstart=[{a:1,c:[{b:1}]},{a:2,c:[{b:2},{b:3}]}];varmiddle=start.map(function(outer){returnouter.c.map(function(inner){return{a:outer.a,b:inner.b};});});//> [ [{ a: 1, b: 1 }], [{a: 2, b: 2}, {a: 2, b: 3}] ]varend=pre.flatten();//> [{a: 1, b: 1}, {a: 2, b: 2}, {a: 2, b: 3}]
Back to business.
We have a suspect in mind: a classmate named "Hack Kerr". He's a nice guy, and he's always been friendly to you - but there's something suspicious about him: his name.
We'll test out flatten, then re-create our student array of data from the original course data.
Array -> anything
We know our likely suspect is also in the school computer system. Perhaps our suspect also changed his grades.
You can't be sure who is a cheater, but you can assume if the grades are well above the average, the person is likely to be the culprit. For this, we'll have to do some basic statistical calculations. We'll need a new tool for transforming arrays into different data representations.
map
has a major limitation: it will always output the same number of elements as the input array.
When you want to transform data into something different, you'll likely want to usereduce
.
Reduce requires two parameters:
- the running total (set by an initialValue)
- the next value in the array
functionadd(total,next){console.log(`add(${total},${next}) ->${total+next}`)returntotal+next}varinitialValue=100;[1,5,10].reduce(add,initialValue);// initial value// add(100, 1) -> 101// add(101, 5) -> 106// add(106, 10) -> 116//> 116
Notice in the example we input an array of 3 items and output a single number. The data has been transformed.
It takes a while to wrap your head aroundreduce
, but once you do, you'll see it's usefulness everywhere.
You may have noticed we've already usedreduce
toflatten
our arrays.
Array.prototype.flatten=function(){returnthis.reduce(function(a,b){returna.concat(b);},[]);};
Withflatten
, the initialValue was set to an empty array which each value wasconcat
onto.
Do some practice withreduce
, before you use it to narrow down a cheating suspect.
About
Functional Programming in Javascript Tutorial
Resources
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Languages
- JavaScript100.0%