FP workshop

Anonymous
516 views

Open Source Your Knowledge, Become a Contributor

Technology knowledge has to be shared and made accessible for free. Join the movement.

Create Content
Previous: Introduction Next: The Pure game.

Functional Programming Definition

"Functional programming is a 'declarative' 'paradigm' of building software by 'composing pure functions', avoiding 'shared state', 'mutable data' and 'side-effects'. Placing the mayor emphasis on the use of functions; 'abstracting control flows and operations on data with these functions and threaten them as building blocks' by relying on 'JS first-class' and 'higher-order functions' to improve the modularity, predictability and reusability of your code.

So, FP essencially boils down to:

  • Program everyting with functions (a "function flow" takes an input and gives an output)
  • Avoid shared mutable state & side-effects (use pure functions)
  • FP is about pulling programs apart and reassembling them from the same parts, abstracted behind function boundaries.

"declarative"

FP is a declarative paradigm software development style, like IP or OOP, thats keeps 'functions' and 'data' separate

"paradigm"

In simple terms, it is a way of thinking about software construction, based on some development style that follow principles.

"composing pure functions"

Composition means that we attach multiple functions together, in a pipe, where the return value of the first function becomes the input for the next function:

Function composition is the process of combining two or more functions in order to produce a new function. Simply put, a composition of functions f . g (the dot means "composed with") can be defined as f(g(x)) (evaluates inside out, right to left = x, g and f)

If you want to compose two functions you are forced to write your own compose function or use the already available ones in libraries such as Lodash and Ramda, also R provides pipe and composition.

Function Composition

Compose and Pipe:

Composition f(g(h(x))) and Pipe are function composition, what is change is the order: Composition: Inside out, Pipe: Outside in.

// using compose on TS
function f() {
    console.log("f(): evaluated");
    return function (target, propertyKey: string, descriptor: PropertyDescriptor) {
        console.log("f(): called");
    }
}
function g() {
    console.log("g(): evaluated");
    return function (target, propertyKey: string, descriptor: PropertyDescriptor) {
        console.log("g(): called");
    }
}
function h() { 
    console.log("h(): evaluated");
    return function (target, propertyKey: string, descriptor: PropertyDescriptor) {
        console.log("h(): called");
    }
}
class C { // some as: f(g(h()))
    @h()
    @f()
    @g()
}
// h(): evaluated
// f(): evaluated
// g(): evaluated
// g(): called
// f(): called
// h(): called

Execure TS code (JSfiddle)

"shared state"

FP avoids shared state, instead relying on immutable data structures and pure calculations.

Shared state is any variable, object, or memory space that exists in a "shared scope", or as the property of an object being passed between scopes.

Problems:

  • Change order:
  • The problem with shared state is that in order to understand the effects of a function, you have to know the entire history of every shared variable that the function uses or affects.
  • Cascade of failures because functions which act on shared state are "timing dependent".
  • Race-condition:
  • A common bug associated to 'share state'is 'race-condition'
With shared state, the order in which function calls are made changes the result of the function calls
1
2
3
4
5
6
7
8
9
// shared-state: 2 -> 3 -> 6
const x = {
val: 2
};
const x1 = () => x.val += 1;
const x2 = () => x.val *= 2;
x1(); // 2 + 1 = 3
x2(); // 3 * 2 = 6
console.log(x.val); // 6
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
This example is exactly equivalent to the above, except the order of the function calls is reversed
1
2
3
4
5
6
7
8
9
10
11
// shared-state: 2 -> 4 -> 5
const x = {
val: 2
};
const x1 = () => x.val += 1;
const x2 = () => x.val *= 2;
// ...the order of the function calls is reversed...
x2(); // 2 * 2 = 4
x1(); // 4 + 1 = 5
// which changes the resulting value:
console.log(x.val); // 5
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Better avoid shared state, the timing and order of function calls don’t change the result of calling the function.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const x = {
val: 2
};
const x1 = x => Object.assign({}, x, { val: x.val + 1});
const x2 = x => Object.assign({}, x, { val: x.val * 2});
console.log(x1(x2(x)).val); // 5
const y = {
val: 2
};
// Since there are no dependencies on outside variables,
// we don't need different functions to operate on different
// variables.
// Because the functions don't mutate, you can call these
// functions as many times as you want, in any order,
// without changing the result of other function calls.
x2(y);
x1(y);
console.log(x1(x2(y)).val); // 5
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

"mutable data"

An mutable object is any object which can be modified after it's created.

"immutable"

An immutable value or object cannot be changed, so every update creates new value, leaving the old one untouched.

For example, if your application state is immutable, you can save all the states objects in a single store to easily implement undo/redo functionality

"pure function"

A pure function is a function which:

  • Given the same input, always return the same output
  • Has no side-effects (immutable)

@ngrx/store have: Reducers: pure + inmutable @effect: NOT pure + inmutable

1
2
3
4
// pure
function add2 (x){
return x + 2;
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1
2
3
4
5
6
// not pure
// impure: because it reads/modifies an external variable, counter, which isn’t local to the function’s scope.
const y = 2;
function adder (x){
return x + y;
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

"side-effects"

Mutating data can cause unintended side-effects.

A side effect is a change of system state or observable interaction with the outside world that occurs during the calculation of a result.

Side effects may include, but are not limited to

  • Anything that rely on current time, it is impure.
  • Anything that rely on random number
  • Changing the file system
  • Inserting a record into a database
  • Making an http call
  • Querying the DOM
  • Accessing system state
  • I/O interaction (user intput, disk access, network access, printing to the screen) is impure throws
// impure function due to use of external non-constants
// The impure function indirectly depends on x
// If you were to change x, then addx would output a different value for the same inputs.
let x = 10
const addx = (a) => a + x
// also impure due to side-effect
const setx = (v) => x = v 

"abstracting control flows and operations on data with these functions and threaten them as building blocks"

Minimizing moving parts

Abstractions **hide details** (abstract me of the detail) and give us the ability to talk about problems at a higher (or more abstract) level.

// calculate squares
const array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

// style using loop 
let arraySquares = [];
for(let i = 0; i < array.length; i++) {
    arraySquares[i] = Math.pow(array[i], 2);
}
console.log(arraySquares); // [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

// style no loop
array.map(x => Math.pow(x, 2)); // [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

"Js First-Class"

Functions in JS are "first-class" objects, this means that something has a value:

```javascript runnable let something = "Leo"; ```

"First-Class-functions" FcF

In JS functions are First-Class and Higher-Order functions

"JS First-Class"

Functions in JS are "first-class" objects, this means that something has a value:

```javascript runnable let something = "FP"; console.log(something); // FP ```

Functions in JavaScript are treated as objects, not just methods: mean that you can STORE 'functions' into a 'variable':

```javascript runnable let subName = function(a,b) { return a + b }; console.log(subName); // ƒ(a,b){ return a + b } ```

"Higher-order-functions" (HoF)

Functions are objects: basically it means that functions are not just methods, chunks of code that act on data, but that they can be passed around as data, can appear as parameters to other functions (known as callbacks)

A function that takes another function as an argument, returns another function, or both.

1
2
3
4
5
6
7
8
9
// yes we can create functions as many other languages
function foo(n){ return n + 1}
// BUT JS also allow us to create an anonimous function AND assign it to a variable
let HoF = function(n){ return n + 1};
// and then pass the function as a variable and execute it, or not
let HoF2 = HoF;
console.log(HoF(2)); // 3
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

This allow us to have Function Composition: The fact that we can take a function and put into another function, allow us to compose a lot of small functions into bigger functions.

Open Source Your Knowledge: become a Contributor and help others learn. Create New Content