KEMBAR78
Functional Programming with JavaScript | PDF
<web/F><web/F>
Functional
Programming
with JavaScript
<web/F><web/F>
Agenda
1. What
a. are functions?
b. is functional programming?
2. How?
3. Why?
4. Cool Stuff
<web/F><web/F>
Ramda lodash-fp
<web/F><web/F>
Functions
A relation f from a set A to a set B is
said to be a function if every element
of set A has one and only one image
in set B.
<web/F><web/F>
Functional Programming is about using
functions as units of abstraction and
composing them to build a system.
<web/F><web/F>
Functional language or a language
facilitating functional programming is one
which supports first-class functions.
<web/F><web/F>
R.map(function (n) {
return addOne(n);
}, list);
<web/F><web/F>
R.map(function (n) {
return addOne(n);
}, list);
R.map(addOne, list);
<web/F><web/F>
$http.get('/list', function(res) {
callback(res);
});
<web/F><web/F>
$http.get('/list', function(res) {
callback(res);
});
$http.get('/list', callback);
<web/F><web/F>
Example: Searching a list
Declarative
var nameEquals = R.compose(
R.match(new RegExp(value, 'i')), R.prop('name')
);
var filtered = R.filter(nameEquals, list);
Imperative
var filtered = [], i = 0, pattern = new RegExp(value, 'i');
for (i = 0; i < list.length; i += 1) {
if (list[i].name.match(pattern)) filtered.push(list[i]);
}
<web/F><web/F>
Higher-order functions
are first-class functions, that can take as
argument or return a function.
<web/F><web/F>
Map, Reduce and Filter
are the three most important functions to
work with collections.
Do not use any of these as a loop.
<web/F><web/F>
If the input and output collections are always
going to be same length, you probably need map.
var double = (x) => x * 2;
R.map(double, [1, 2, 3]); //=> [2, 4, 6]
<web/F><web/F>
If the output collection can have lesser or equal
number of items, you probably need filter.
var isEven = (n) => n % 2 === 0;
R.filter(isEven, [1, 2, 3, 4]); //=> [2, 4]
<web/F><web/F>
You probably need reduce when the input is a
collection and the output is a single value.
Reduce is also known as fold.
R.reduce(R.add, 0, [1, 2, 3]); //=> 6
<web/F><web/F>
Map, Reduce and Filter are low-level. There
are many others provided by libraries, which
can be a better fit.
<web/F><web/F>
Example: Given an array of objects, get only the
‘name’ property values in an array.
R.map(R.prop('a'), [{a: 1}, {a: 2}]);
// pluck :: k -> [{k: v}] -> v
R.pluck('a', [{a: 1}, {a: 2}]); //=> [1, 2]
<web/F><web/F>
1. Functions should be simple.
2. They should do and focus on only one thing.
3. Try writing small functions.
4. Do not mix concerns
Ref: Simple Made Easy by Rich Hickey
<web/F><web/F>
Create lot of functions
Don’t be afraid to create many small functions.
Abstract whenever two functions seems to do similar
things or some part of them are similar.
<web/F><web/F>
Open/closed principle
states "software entities (classes, modules,
functions, etc.) should be open for extension,
but closed for modification"
Ref: https://en.wikipedia.org/wiki/Open/closed_principle
<web/F><web/F>
Function Composition
var x' = f(x) ;
var x'' = g(x'); } g(f(x));
var h = R.compose(g, f); h(x);
<web/F><web/F>
Example
// notDone :: Object -> Boolean
var notDone = function (todo) {
return !todo.done;
}
var notDone =
R.compose(R.not, R.prop('done'));
<web/F><web/F>
// wordCount :: String -> Number
var wordCount = function (s) {
return s.split(' ').length;
}
var wordCount = R.compose(
R.length, R.split(' ')
);
wordCount('How many words?') //=> 3
<web/F><web/F>
Pass and return functions
If some function accepts many parameters to
perform some part of its operations try to
replace with function instead.
<web/F><web/F>
Example: Pass function
function createBuiltFile (packageName, minifier, extension, files) {
...
var name = packageName + '.' + md5(content) + '.' + extension;
...
}
function createBuiltFile (minifier, nameGenerator, files) {
...
var name = nameGenerator(content);
...
}
<web/F><web/F>
Pass functions instead of values
when you want to make a function more
generic.
<web/F><web/F>
Work with simple data structures such
as Arrays and Objects
<web/F><web/F>
Curried Functions
A function that returns a new function until it
receives all its arguments.
Originated by
Moses Schönfinkel
Developed by
Haskell Curry
<web/F><web/F>
// add :: Number -> Number -> Number
var add = R.curry(function (x, y) {
return x + y;
});
// addOne :: Number -> Number
var addOne = add(1); addOne(5); //=> 6
A curried function can be easily specialized for
your own needs.
<web/F><web/F>
fetchFromServer()
.then(JSON.parse)
.then(function(data){ return data.posts })
.then(function(posts){
return posts.map(function(post){
return post.title;
});
})
fetchFromServer()
.then(JSON.parse)
.then(R.prop('posts'))
.then(R.map(R.prop('title')))
Read: Why Curry Helps?
<web/F><web/F>
Partial Application
// propEq :: k -> v -> {k: v} -> Boolean
var idEqZero = R.propEq('id', 0);
in this example we say that R.propEq has been
partially applied.
<web/F><web/F>
● Helps you build new functions from old
one.
● Think of it as configuring a function for
your needs.
● It also makes composition easier.
<web/F><web/F>
● Declarative
● Easy to reason about
● Easy to test
Why Functional Programming Matters (by John Hughes)
<web/F><web/F>
Cool Stuff
<web/F><web/F>
Functional null checking
if (x !== null && x !== undefined) {
f(x);
}
<web/F><web/F>
Functional null checking
if (x !== null && x !== undefined) {
f(x);
}
Maybe(x).map(f); //=> Maybe(f(x))
<web/F><web/F>
Functional null checking
if (x !== null && x !== undefined) {
f(x);
}
R.map(f, Maybe(x)); //=> Maybe(f(x))
<web/F><web/F>
Functional null checking
if (x !== null && x !== undefined) {
f(x);
}
R.map(f, Maybe(x)); //=> Maybe(f(x))
var g = R.compose(R.map(f), Maybe);
g(x); //=> Maybe(f(x)) only if x != null
<web/F><web/F>
Functional null checking
if (x !== null && x !== undefined) {
f(x);
}
R.map(f, Maybe(x)); //=> Maybe(f(x))
<web/F><web/F>
Functional null checking
if (x !== null && x !== undefined) {
f(x);
}
R.map(addOne, Maybe(2)); //=> Maybe(3)
R.map(addOne, [2]) //=> [3]
<web/F><web/F>
Both Maybe and Array are Functors.
<web/F><web/F>
Functor is something that implements map.
Some Functors are Array, Maybe, Either,
Future and many others.
<web/F><web/F>
Fantasy Land Specification
https://github.com/fantasyland/fantasy-land
<web/F><web/F>
bilby.js Folktale
ramda-fantasy
<web/F><web/F>
● Start writing more functions
● Preferably pure and simple functions
● Glue your functions using higher-order
functions
● Use a functional library
● Discover!
<web/F><web/F>
References
Books
● http://functionaljavascript.com/
● https://leanpub.com/javascriptallongesix/
● https://github.com/DrBoolean/mostly-adequate-guide
Talks
● https://www.youtube.com/watch?v=AvgwKjTPMmM
● http://scott.sauyet.com/Javascript/Talk/2014/01/FuncProgTalk/
● https://www.youtube.com/watch?v=m3svKOdZijA
<web/F><web/F>
Thank You!
Debjit Biswas
@debjitbis08
https://in.linkedin.com/in/debjitbis08

Functional Programming with JavaScript