johnny-dreamguns
10/9/2019 - 3:28 PM

Functional Lite

Functional Lite Programming

Pure function - a function that has no side effects. When called it should return a value without changing the state of the system

Side effect - A change that occurred indirectly when a function was called

Making things pure makes programs easier to write and read. It makes things more reasonable and less complex

A pure function can access state as long as it doesn’t change it

Example of impure function

function foo(x){
  y = y * x;
  z = z * x;
}

let y = 2, z = 3;

foo(5);

Example of pure function

function bar(x, y, z){
  foo(x);
  return [y,z];

  function foo(x){
    y = y * x;
    z = z * x;   
  }
}

bar(5, 2, 3); 

Manual Composition

The output of one function is the input of another function

Make code pure using manual composition

In this example the side effect doesn’t cause different values to return but there’s still a side effect by changing the value of z

function sum(x, y){
  return x + y;
} 

function mult(x, y){
  return x * y; 
}

let z = mult(3, 5);
z = sum(z, 2);

It would be better written using composition in a utility function like so:

function multAndSum(x, y, z){
  return sum(mult(x, y), z);
}
multAndSum(3, 5, 2);

Immutability

non mutation - the non ability to change value

How const and Object.freeze work

var x = 2;
x++; // allowed


const y =3;
y++; // not allowed


const z = [4,5,6];
z = 10; // not allowed
z[0] = 10; // allowed


const w = Object.freeze([4,5,6]);
w = 10; // not allowed
w[0] = 10; // not allowed

Object.freeze only affects the top level

Dangers

Very easy to change values as each variable is just a reference to an object

If two variables reference the same object then it’s possible to change both when not intended

let myArr = [1,2,3]
let myArr2 = myArr
myArr2[0] = 4
console.log(myArr[0]) // 4

Immutability as a discipline

Immutability is a discipline, given values we choose not to change them

Whether the value is changeable is not really the point

Instead of making a reference to an array and changing it or one of it’s values, we should make a new copy of it and work with that. I will not mutate it.

In a functional programming language you cannot mutate state

In JavaScript we can choose not to mutate state instead

Immutable example

function doubleThemMutable(list) {
  for(var i=0; i<list.length; i++){
    list[i] = list[i] * 2;
  }
}


function doubleThemImmutable(list) {
  var newList = []
  for(var i=0; i<list.length; i++){
    newList[i] = list[i] * 2;
  }
  return newList;
}

Passing variables to functions

Simple primitives are passed as new copies Non-simple primitives are passed as references

Closure

Closure is when a function ‘remembers’ the variables around it when that function is executed elsewhere

A non functional example of closure

function foo() {
  var count = 0;

  return function() {
    return count++;
  }
}

const x = foo();
x(); // 1
x(); // 2
x(); // 3

State is being modified here so it isn’t pure

Useful example of closure / currying

function foo(x, y) {
  return function(){
    return x + y;
  }
}

var x = foo(3, 4);

x(); // 7

x() will return 7 every time

3 and 4 are stored in the closure

Recursion

A function you define that’s going to perform an action and call itself until it reaches a base case

A recursive function:

• Has a base case • Calls itself using it’s own name to call

Mutual Recursion

More than one function calling each other until they reach a base case

More about Recursion

There are physical limitations on how many executing functions that can be stored in memory

A stack frame is stored in memory when a function is called, IE used to have a limit of 13 functions that could be calling each other at once

These days the limit is much larger but still a concern

There is a performance optimisation in ES6, if you use a proper tail call then the recursion will only use one stack frame no matter how deep

Non recursive way to sum 3 numbers

function sumIter(){
  var sum = 0;
  for(var i=0; i<arguments.length; i++){
    sum = sum + arguments[i];
  }
  return sum;
}

console.log(sumIter(3,4,5)); // 12

Recursive solution

function sumRecursive(...args) {
  if(args.length <= 2){
    return args[0] + args[1];
  }
  return(
    args[0] + 
    sumRecursive(...args.slice(1))
  )
}

console.log(sumRecursive(3,4,5)); // 12

Slice - good example of an immutable method

The slice array method is good for immutability as it returns a new array rather than modifying the one it is run on

List Transformation (map)

A transformation is taking a value and doing something to it so you get a different value

The map operation runs a function against every item in a list and returns a new list that is the same length with the new values calculated by the function

Map is useful in functional programming as it returns a new array so is good for maintaining immutability

Map is a prototypal method of the Array object which makes it harder to compose, composition is done through chaining calls together

It is however really easy to use

The predicate is the transformer function you pass in

If we wanted to run two map functions we want to run on an array it is preferable to combine the functions into one and only do one map operation. We shouldn’t be chaining multiple map and filter calls ideally

function doubleIt(v) {
  return v * 2;
}

console.log([1,2,3,4,5].map(doubleIt));

List Exclusion (filter)

You can filter an array using a predicate function, the value returned determines if the array items are included in the new array or not

If you want to include / exclude based on something more complicated than just the value then you shouldn’t use filter

Filter is an immutably principled operation, it returns a new array

The new list has potentially fewer items, maybe none

If the predicate returns a true value for a value it is included in the new array, otherwise it isn’t

function isOdd(v){
  return v % 2 == 1;
}

console.log([1,2,3,4,5].filter(isOdd));

List composition (reduce)

An example of a reduction would be to get the summation of every item in a list

The reduce operation is more complex than the previous two

It is easy to not use this functionally

The parameters passed to the predicate are called the the accumulator and the value

An initial value is passed in the the reduce predicate, for multiplication this should be 1, for summation this should be 0

Reduce returns a result that isn’t necessarily an array but could be

A partial reduction returns another list

function mult(x, y){
  return x * y;
}

[1,2,3,4,5].reduce(mult, 1)

List iteration (forEach)

The only way that forEach is useful is if the predicate has a side effect

For this reason it is not pure

Most functional programmers will tell you never to use forEach, it’s all about side effects

Wrapping values in functions It can be useful sometimes to wrap values in functions

e.g.

function foo(){
  return 42;
}

A function wrapped around a value is called a thunk

Other functional programming languages

Will provide map and reduce but not filter, you can make filter easily using map and reduce

Functional programming things to look up later

Predicate Monad Writing recursive functions Y combinator, alternative to recursion Ramda, baconJs