Functional JS
JaxNode July 2017
Upcomming events
- Jax Tech Meetup on August 11th
- CodeImpact in August 26th
Sponsors
- Availity
- Interactive Resources
- Swyft Technology
JaxNode is looking
for Speakers!!!
- Electron
- Go Lang
- Kubernetes, Swarm or Mesos
- Client Side frameworks
- WebAssembly/WASM
- NAPI
- Any other JavaScript topic
- JavaScript History
- Pure Functions
- Closures
- Classes vs Object Literals
- Currying
- Higher Order Functions
- Functors
- Monads
- Promises
- Async/Await
- Immutability
- Bind and Pipe Operator proposals
Topics
Douglas Crockford
"JavaScript is the only programming language that people try to program in before actually learning the language"
Brendan Eich
Hired by Netscape
Wanted to do Scheme
Had to look like Java
We got JavaScript
Functional Programming
- Is a programming paradigm
- Declarative over Imperative
- Avoid changing state and mutability
- Create structures of elements
- Uses functions for computational change
- Try to use Pure Functions
- Avoid Side-effects
Why learn functional programming?
- Because it is AWESOME!
- Many JS frameworks like React and Redux based on functional programming concepts
- Helps you write code with less errors
- Generally results in less code
Functional Langages
- Lisp
- Haskell
- Erlang
- F#
- Scala
- Elixir
- Elm
Is Javascript functional?
- Functions are first class citizens
- Closures allow inner functions to access parents scope
- Functions can be passed as parameters
- Functions can be returned from functions
- Global scope can be problemattic
pure functions
function add(a, b) {
return a + b;
}
const c1 = add(12, 14); // 26
const c2 = add(100, -1); // 99
const c3 = add(34, 17); // 51
non-pure functions
let state = 0;
function addToState(value) {
state += value;
return state;
}
let c1 = addToState(3); // 3
let c2 = addToState(10); // 13
let c3 = addToState(3); // 16
closures
const counter = function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
};
};
const myCounter = counter();
myCounter.increment(); // Changes privateCounter to 1
myCounter.value(); // returns 1
Es6/2015 and other Controversies
- 'class' and 'super' keyword
- 'new' keyword
- Functional programmers should try to avoid these
C# Class
// C#
public class Animal {
public string Name { get; set; }
public int Limbs { get; set; }
public Animal(name, limbs) {
this.Name = name;
this.Limbs = limbs;
}
public void printAnimal() {
if (this.Limbs == 0) {
Console.PrintLine(@"You have a " +
this.Name + " with no limbs.");
} else if (this.Limbs == 1) {
Console.PrintLine(@"You have a " +
this.Name + " with " +
this.Limbs.ToString() + " limb.");
} else {
Console.PrintLine(@"You have a " +
this.Name + " with " +
this.Limbs.ToString() + " limbs.");
}
}
}
ES6/2015 class
class Animal {
constructor(name, limbs) {
this.Name = name;
this.Limbs = limbs;
}
printAnimal() {
if (this.Limbs === 0) {
console.log(`You have a ${this.Name} with no limbs.`);
} else if (this.Limbs === 1) {
console.log(`You have a ${this.Name} with ${this.Limbs} limb.`);
} else {
console.log(`You have a ${this.Name} with ${this.Limbs} limbs.`);
}
}
}
es6 class invocation
const Cat = new Animal('Gato', 4);
const Dog = new Animal('Perro', 3);
Cat.printAnimal(); // You have a Gato with 4 limbs.
Dog.printAnimal(); // You have a Perro with 3 limbs.
$('#myButton').on('click', Cat.printAnimal()); // Doesn't work
$('#myButton').on('click', Cat.printAnimal.bind(this)); // Will work
$('#myButton').on('click', _ => Cat.printAnimal()); // Will work
Object literal classes
const MakeAnimal = (name, limbs) => {
const Name = name;
const Limbs = limbs;
return {
printAnimal: () => {
if (Limbs === 0) {
console.log(`You have a ${Name} with no limbs.`);
} else if (Limbs === 1) {
console.log(`You have a ${Name} with ${Limbs} limb.`);
} else {
console.log(`You have a ${Name} with ${Limbs} limbs.`);
}
}
}
};
Alternatives to new and super
- Douglas Crockford proposed Object.create()
- Avoids having constructors
- Object.create(proto[, propertiesObject])
- by default properties ARE NOT writable,
enumerable or configurable
const person = {
sayName: function () {
console.log(`my name is ${this.myName}`)
}
}
const bar = Object.create(person);
bar.myName = 'Dinesh';
bar.sayName(); // my name is Dinesh
// This property is overwritable
bar.myName = 'Gilfoyle';
bar.sayName(); // my name is Gilfoyle
const baz = Object.create(person,
{ myName: {
get: function() { return 'Erlich'; }
}
});
baz.sayName(); // my name is Erlich
baz.myName = 'Richard'; // Will throw error! This property is not overwritable.
Object composition over inheritance
- Object.assign() to create new object from multiple objects and properties
- Helps avoid the Gorilla Banana problem with classical inheritance chains
- Used with Redux and React for transforming state
const sounder = (state) => ({
makeSound: () => console.log(state.sound)
});
const namer = (state) => ({
sayName: () => console.log(`My name is ${state.name}.`)
})
const state = {
name: 'Bill',
sound: 'Ack Ack!'
};
const cat = Object.assign({}, sounder(state), namer(state));
cat.makeSound(); // Ack Ack!
cat.sayName(); // My name is Bill.
Currying
- Currying allows for partial application of function calls
- Syntax can look like: myFunction('Red')('Blue')
- Functions can return other functions or themselves
Currying
const greeter = function(greeting) {
return function(name) {
console.log(`${greeting} there ${name}!`);
}
};
const greet = greeter('Hi');
greet('David'); // Hi there David!
greet('Andy'); // Hi there Andy!
// or
greeter('Hi')('Frank'); // Hi there Frank!
Higher order functions
- higher order functions accept functions as parameters
- filter, map and reduce all considered higher order
- => operator can be used for short form
- Declarative over Imperative example
Imperative filter
function filterGT2(arr) {
let newArray = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i] > 2) {
newArray.push(arr[i]);
}
}
return newArray;
}
console.log(filterGT2([-1, 0, 1, 2, 4, 5, 7]));
// returns [4, 5, 7];
higher order filter
console.log([-1, 0, 1, 2, 4, 5, 7].filter(i => i > 2));
// returns [4, 5, 7]
MAP
const multipleBy2 = (item) => item * 2;
[3, 4, 8, 5].map(multipleBy2); // returns [6, 8, 16, 10]
Reduce
const arr = [ 6, 8, 16, 10 ];
const sum = arr.reduce((a, i) => a += i, 0); // returns 40
Functors
- Implements Map
- Holds a set of values
- Map returns a Functor of the same size
- Array object is an example of a Functor
- filter, map and reduce all can return Functors
Douglas Crockford
Once someone learns what a Monad is, it becomes physically impossible for them to describe what a Monad is to someone else.
Crockford on Monads
Monads
- Monads are a type of Functor
- Monads generally implement some form of FlatMap
- Allow developers to manage side effects
- Promises are a form of Monad
- JQuery object is also a Monad
- Highland JS library also a Monad
Promises
- Easier implementation for handling asynchronous callbacks
- Original pattern in JS was the error first callback
- fs.open('myfile', 'wx', (err, fd) => { ... })
- Could be implemented with a Promise like this;
- fs.open('myfile').then(d => { ... }).catch(err => log(err))
- async and await keywords use promises
Error first callback
const fs = require('fs');
fs.stat('.', function cb(err, result) {
if (err) {
console.error(err);
}
console.log(result);
});
Promise
fetch('https://www.jaxnode.com/v1/api/meeting')
.then(response => {
return response.json();
})
.then(json => {
console.log(json);
})
.catch(err => {
console.error(err);
});
Defining a promise
// Copyright Mozilla.org
function myAsyncFunction(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.onload = () => resolve(xhr.responseText);
xhr.onerror = () => reject(xhr.statusText);
xhr.send();
});
});
Node 8 util.promisfy
const util = require('util');
const fs = require('fs');
const stat = util.promisify(fs.stat);
stat('.')
.then((stats) => {
console.log(stats);
})
.catch((error) => {
console.error(error);
});
promises with async await
const util = require('util');
const fs = require('fs');
const stat = util.promisify(fs.stat);
async function callStat() {
const stats = await stat('.');
console.log(`This directory is owned by ${stats.uid}`);
}
"50% of the bugs that people run into today, coding with C# in our platform, and the same is true of Java for that matter, are probably null reference exceptions. If we had had a stronger type system that would allow you to say that ‘this parameter may never be null, and you compiler please check that at every call, by doing static analysis of the code’. Then we could have stamped out classes of bugs."
Anders Hejlsberg
IMMUTABLE JS
- JS library to prevent user from changing variables
- Has set of types for Map, List, Range and others.
- Avoid null!!!
- State is the source of many errors, and is the root of all EVIL!
- ES6/2015 introduced 'const' and 'let' keywords
- Try to use 'const' and 'let' keywords over 'var'
- Mori is a library based on Closure script that does many of the same things as Immutable JS
Bind & Pipe Operator
- ES Proposal for Bind and Pipe operators
- Bind operator would use ::
- Pipe operator would use |>
// Copyright 2017 Michael K. Snead
// https://medium.com/@aikeru/can-we-please-promote-the-bind-operator-939845ca6ae5
function pipeline(fn, ...args) {
return fn && fn(this, ...args)
}
//Used like so
const addAll = (...numbers) => numbers.reduce((a, b) => a + b);
5 :: pipeline(addAll, 2);
// copyright 2016 https://github.com/gilbert/es-pipeline-operator
function doubleSay (str) {
return str + ", " + str;
}
function capitalize (str) {
return str[0].toUpperCase() + str.substring(1);
}
function exclaim (str) {
return str + '!';
}
let result = exclaim(capitalize(doubleSay("hello")));
console.log(result); //=> "Hello, hello!"
let result2 = "hello"
|> doubleSay
|> capitalize
|> exclaim;
console.log(result2); //=> "Hello, hello!"
result2
|> console.log; // => "Hello hello!"
Questions ?
resources
https://github.com/jaxnode/functionaljavascript
Anjana Vakil
https://www.youtube.com/watch?v=e-5obm1G_FY
https://www.youtube.com/watch?v=Wo0qiGPSV-s
Eric ElliotT @_ericelliott
@mpjme FunFunFunction
Douglas Crockford
Functional JavaScript
By David Fekke
Functional JavaScript
These are the slides for the Functional JavaScript presentation for JaxNode
- 1,677