Functional Programming (FP)

Andres Bedoya G. (A.K.A. Angelfire)

What is functional Programming?

(programming paradigm) Is the process of building software by composing pure functions, avoiding shared state, mutable data, and side-effects. Functional programming is declarative rather than imperative, and application state flows through pure functions.

Declarative vs Imperative

Functional programming is a declarative paradigm, meaning that the program logic is expressed without explicitly describing the flow control.

Imperative programs spend lines of code describing the specific steps used to achieve the desired results — the flow control: How to do things.

Declarative programs abstract the flow control process, and instead spend lines of code describing the data flow: What to do. The how gets abstracted away.

const doubleMap = numbers => {
  const doubled = [];
  for (let i = 0; i < numbers.length; i++) {
    doubled.push(numbers[i] * 2);
  }
  return doubled;
};
const doubleMap = numbers => numbers.map(n => n * 2);

Examples of commonly used statements include for, if, switch, throw, etc…

map, filter, reduce, concatAll, zip...

Pure functions

A pure function is a function which:

  • Given the same input, will always return the same output.
  • Produces no side effects.
  • Relies on no external mutable state.

Impure functions

  • Everything that relies on the current time
  • Random numbers
  • Anything that depends on I/O (user, disk, network)
// impure addToCart mutates existing cart
const addToCart = (cart, item, quantity) => {
  cart.items.push({
    item,
    quantity
  });

  return cart;

};
const time = () => new Date().toLocaleTimeString();
time(); // "11:20:35 AM"

Math.random(); // 0.13196662441712692
Math.random(); // 0.3356794546270385
Math.random(); // 0.9819770414694777
// Pure addToCart() returns a new cart
// It does not mutate the original.
const addToCart = (cart, item, quantity) => {
  const newCart = lodash.cloneDeep(cart);

  newCart.items.push({
    item,
    quantity
  });

  return newCart;

};

Function

composition

Is the process of combining two or more functions in order to produce a new function or perform some computation. For example, the composition f . g (the dot means “composed with”) is equivalent to f(g(x)) in JavaScript.

const compose = (func1, func2) => (value) => func1(func2(value));

const double = x => x * 2;

const triple = x => x * 3;

const composed = compose(double, triple);

console.log(composed(3)); // 18

Shared state

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. A shared scope can include global scope or closure scopes. Often, in object oriented programming, objects are shared between scopes by adding properties to other objects.

// With shared state, the order in which function calls are made
// changes the result of the function calls.
const x = {
  val: 2
};

const x1 = () => x.val += 1;

const x2 = () => x.val *= 2;

x1();
x2();

console.log(x.val); // 6

x2();
x1();

console.log(x.val); // 5
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
};

x2(y);
x1(y);

console.log(x1(x2(y)).val); // 5

request 1: updateBio() -> (save button) -> updateUser()

request 2: updateAvatar() -> (save button) -> updateUser()

Immutability

An immutable object is an object that can’t be modified after it’s created. Conversely, a mutable object is any object which can be modified after it’s created.

const a = {
  foo: 'Hello',
  bar: 'MDEJS',
  baz: '!'
};

a.foo = 'Goodbye';
// 'Goodbye'

const a = Object.freeze({
  foo: 'Hello',
  bar: 'MDEJS',
  baz: '!'
});

a.foo = 'Goodbye';
// Error: Cannot assign to read only property 'foo' of object Object
const a = Object.freeze({
  foo: { greeting: 'Hello' },
  bar: 'MEDJS',
  baz: '!'
});

a.foo.greeting = 'Goodbye';

console.log(`${ a.foo.greeting }, ${ a.bar }${a.baz}`);

Side Effects

A side effect is any application state change that is observable outside the called function other than its return value. Side effects include:

  • Modifying any external variable or object property (e.g., a global variable, or a variable in the parent function scope chain)
  • Logging to the console
  • Writing to the screen
  • Writing to a file
  • Writing to the network
  • Triggering any external process
  • Calling any other functions with side-effects

Haskell and other functional languages frequently isolate and encapsulate side effects from pure functions using monads.

HOF

A higher order function is any function which takes a function as an argument, returns a function, or both. Higher order functions are often used to:

  • Abstract or isolate actions, effects, or async flow control using callback functions, promises, monads, etc…
  • Create utilities which can act on a wide variety of data types
  • Partially apply a function to its arguments or create a curried function for the purpose of reuse or function composition
  • Take a list of functions and return some composition of those input functions

Reusability Through Higher Order Functions

Functional programming tends to reuse a common set of functional utilities to process data. Object oriented programming tends to colocate methods and data in objects. Those colocated methods can only operate on the type of data they were designed to operate on, and often only the data contained in that specific object instance.

In functional programming, any type of data is fair game. The same map()utility can map over objects, strings, numbers, or any other data type because it takes a function as an argument which appropriately handles the given data type. FP pulls off its generic utility trickery using higher order functions.

Containers, Functors, Lists, and Streams...

Conclusion

  • Pure functions instead of shared state & side effects
  • Immutability over mutable data
  • Function composition over imperative flow control
  • Lots of generic, reusable utilities that use higher order functions to act on many data types instead of methods that only operate on their colocated data
  • Declarative rather than imperative code (what to do, rather than how to do it)
  • Expressions over statements
  • Containers & higher order functions over ad-hoc polymorphism

Thank you!

Functional Programming

By Andrés BG

Functional Programming

Functional Programming

  • 1,231