DEV Community

delph
delph

Posted on

functional programming with javascript

what is functional programming?

Functional programming follows a few core principles:

  • Pure functions, ie.

    • the same input always gives the same output
    • limited side effects: any changes, or mutations, to the state of the program outside the function are carefully controlled
  • Function composition: build a complex system by combining more basic components/ functions

In languages that support functional programming (like JavaScript, Ruby, Scala, etc), functions are first-class objects. This means that functions can be assigned to a variable, passed into another function as arguments, or returned from another function just like any other normal value.

Imperative vs declarative

Functional programming is a form of declarative programming. This means that you tell the computer what to do, rather than how to do it (ie. the how gets abstracted away).

This can be done by calling methods or functions. JavaScript offers many predefined methods that handle common tasks so we do not need to write out how the computer should perform them. For example, instead of writing a for loop, the map method can handle the details of iterating over an array.

An advantage of this is that it helps to avoid semantic errors, like the "Off By One Errors".

Mutating vs non-mutating methods

In functional programming, a function should not cause side effects by altering any variable or object in the code. (ie. a function should be non-mutating).

In frameworks/ libraries like React and Redux, a core principle is that you should not mutate the state.

  • slice, map, filter, reduce, concat are some non-mutating methods in JavaScript (ie. these methods return a new array)
  • splice, push, pop, sort are mutating (ie. these methods change the original array)

TIP: .slice() is an easy way to make a copy of the entire array. With ES6 (and beyond), you can also use the spread operator to easily make a copy of an array or object.

const array = ['a', 'b', 'c'];
const object = {message: 'hello world'};

// ES5
const newArray = array.slice();
const newObject = Object.assign({}, object);

// Spread operator
const newArray2 = [...array];
const newObject2 = {...object};

TIP: To sort an array, concatenate an empty array to the one being sorted (since concat returns a new array), then run the sort method.

const array = [1 , 4, 5, 3]

const newArr = array.concat([]).sort()

console.log(array) // [1, 4, 5, 3]
console.log(newArr) // [1, 3, 4, 5]

Currying and Partial Application

The arity of a function is the number of arguments it requires. Currying a function means to convert a function with multiple arguments into a series of functions with a single argument (ie. from arity of N into N functions of arity 1)

In other words, it restructures a function so it takes one argument, then returns another function that takes the next argument, and so on.

//Un-curried function
const add = (a, b) => a + b

//Curried function
const curriedAdd = a => b => a + b

curriedAdd(1)(2) // Returns 3

Currying allows for function composition and gives us the ability to create reusable functions. In cases where all the arguments to a function cannot be supplied at one time, we can save each function call into a variable. That variable will hold the returned function reference that takes the next argument when it's available.

Similarly, partial application applies a few arguments to a function at a time and returns another function that takes fewer arguments.

Top comments (0)