Skip to content

Functional Programming

Martijn Keesmaat edited this page Nov 28, 2019 · 1 revision

What is functional programming

Functional programming is a style of programming where solutions are simple, isolated functions, without any side effects outside of the function scope.

According to FCC it comes down to these points

  1. Isolated functions - there is no dependence on the state of the program, which includes global variables that are subject to change
  2. Pure functions - the same input always gives the same output
  3. Functions with limited side effects - any changes, or mutations, to the state of the program outside the function are carefully controlled

As Danny used in his presentation

INPUT -> PROCESS -> OUTPUT

The death of for loops

What I notice when people talk about functional they are disgusted by for loops. For loops have become the new jQuery. ES6 provides us with a lot of array methods that are supposed to be better than for loops. The main pro of these methods is that they extend the functionality of for loops and make your code more readable. I don't think that for loops should be discarded in its entirety. The biggest benefit of a for loop is it's speed. During my internship at Superhero Cheesecake we primarily used for loops. We used for loops to animate high amounts of vices. Performance matters a lot with animation. Especially when you work 3D animations. Everything that can be optimized, should be optimized. This means using for loops over array methods.

Mutability

During the FP course at FreeCodeCamp, you learn about how certain methods are more FP friendly.

Map vs forEach

Use map over forEach for modifying arrays

Remember that the map method is a way to iterate over each item in an array. It creates a new array (without changing the original one) after applying a callback function to every element.

Slice vs Splice

Use slice over splice since it doesn't mutate the source

The slice method returns a copy of certain elements of an array. It can take two arguments, the first gives the index of where to begin the slice, the second is the index for where to end the slice (and it's non-inclusive). If the arguments are not provided, the default is to start at the beginning of the array through the end, which is an easy way to make a copy of the entire array. The slice method does not mutate the original array, but returns a new one.

Concat vs Push

Use concat over push since it doesn't mutate the source

Concatenation means to join items end to end. JavaScript offers the concat method for both strings and arrays that work in the same way. For arrays, the method is called on one, then another array is provided as the argument to concat, which is added to the end of the first array. It returns a new array and does not mutate either of the original arrays. Here's an example:

[1, 2, 3].concat([4, 5, 6]);
// Returns a new array [1, 2, 3, 4, 5, 6]

var arr = [1, 2, 3];
arr.push([4, 5, 6]);
// arr is changed to [1, 2, 3, [4, 5, 6]]
// Not the functional programming way

Chaining

function getRating(watchList) {
  // Add your code below this line
  const moviesFound = watchList.filter(i => (i.Director = 'Christopher Nolan'));
  const averageRating =
    watchList
      .filter(i => (i.Director = 'Christopher Nolan'))
      .map(i => parseInt(i.imdbRating))
      .reduce((a, b) => a + b) / moviesFound.length;

  // Add your code above this line
  return averageRating;
}

Currying

The arity of a function is the number of arguments it requires. Currying a function means to convert a function of N arity 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.

This is useful in your program if you can't supply all the arguments to a function at one time. You can save each function call into a variable, which will hold the returned function reference that takes the next argument when it's available. Here's an example using the curried function in the example above:

Is Javascript a functional language?

In short no, but it can be.

There's no accepted definition of functional programming language. However, there are common traits. Usually, a functional language needs these things

  • First-class functions (functions that can be used as a value)
  • Lambda Expressions (anonymous functions)
  • Immutability (not allowed to update/overwrite data)
  • Recursion (a function that calls itself)
  • Currying (the arity(n of args) equals one)

Javascript can support all of these. However, they are not required. If you mutate a variable in JS you won't receive any errors. Javascript is an interesting language since it's flexible. It's also loosely typed which doesn't require to define what type your variables have. All this can make Javascript great, but also error sensitive. Before I dive deeper into the flexibility of JS, I should stop with this message: "Javascript is not strictly a functional language, but it supports the traits of one".

What are the alternatives to functional

In class, Danny showed us how to get a good overview of a subject. Our subject being functional programming. What you do is search your subject's wiki page. Then in the side-bar you will see an tree view which you can traverse. If you do this with functional programming you end up at the wiki page of programming paradigms.

Here you will see that there are two main types of programming. Each one has their respective paradigms:

Imperative in which the programmer instructs the machine how to change its state,

  • procedural which groups instructions into procedures,
  • object-oriented which groups instructions together with the part of the state they operate on,

Declarative in which the programmer merely declares properties of the desired result, but not how to compute it

  • functional in which the desired result is declared as the value of a series of function applications, logic in which the desired result is declared as the answer to a question about a system of facts and rules,
  • mathematical in which the desired result is declared as the solution of an optimization problem

Is React imperative?

When I read that I was wondering if React is imperative. Since React works primarily with the state. This Stack Overflow thread provides a lot of valuable answers to this question.

I found this answer to be the clearest:

It is best to compare React (declarative) and jQuery (imperative) to show you the differences.

In React, you only need to describe the final state of your UI in the render() method, without worrying about how to transition from previous UI state to the new UI state. E.g.,

render() {
  const { price, volume } = this.state;
  const totalPrice = price * volume;

  return (
    <div>
      <Label value={price} className={price > 100 ? 'expensive' : 'cheap'} ... />
      <Label value={volume} className={volume > 1000 ? 'high' : 'low'} ... />
      <Label value={totalPrice} ... />
      ...
    </div>
  )
}

On the other hand, jQuery requires you to transition your UI state imperatively, e.g, selecting the label element and update its text and CSS:

onPriceUpdated(price) {
  $("#price-label").val(price);
  $("#price-label").toggleClass('expansive', price > 100);
  $("#price-label").toggleClass('cheap', price < 100);
  updateTotalPrice();
}

onVolumeUpdated(volume) {
  $("#volume-label").val(volume);
  $("#volume-label").toggleClass('high', volume > 1000);
  $("#volume-label").toggleClass('low', volume < 1000);
  updateTotalPrice();
}

updateTotalPrice() {
  const totalPrice = price * volume;
  $("#total-price-label").val(totalPrice);
  ...
}

So after reading this. Why would one ever use this imperative style of coding?

This article presents an argument that makes sense.

We should use OOP when:

we are going to be performing few operations on lots of different variants that have common behavior. In other words, when we have more things with few operations.

Clone this wiki locally