DEV Community

loading...

Functional Programming (Light) #1

sebring profile image J. G. Sebring Updated on ・3 min read

Introduction

I’ve come across the word functional programming (FP) from time to time but never really cared about it, thinking it's some conservative old-school paradigm opposed to Object Oriented Programming, similar to Procedural Programming.

Luckily I came across the expression FP so many times recently I started to look it up. After reading a book on the topic (link below) i realized my first assumption was wrong, completely wrong actually.

Benefits of FP

Functional programming is very simply put a coding style where you chop up your logic into smaller, much smaller functions. These functions can be reused and tested individually. As they are tiny, they are easy to grasp and can (should!) be named informatively and non-generic.

All this will help us keeping code in line with the most important yet basic design principles (DRY, SOLID, POLE, POLK etc).

Example

Consider a list of clients objects (simplified of course to focus on the difference).

const clients = [
  { id: 1, hasDevice: true, age: 72 },
  { id: 2, hasDevice: false, age: 63 },
  { id: 3, hasDevice: false, age: 84 },
  { id: 4, hasDevice: true, age: 75}
]
Enter fullscreen mode Exit fullscreen mode

Now, let’s say we want to get all id of clients without device and older than 70.

let elderlyWithDevice = []
const MAX_AGE = 70

// 1. the classic for-loop 
for (let i = 0; i < clients.length; i++) {
  if (clients[i]).hasDevice && clients[i].age > MAX_AGE) {
    elderlyWithDevice.push(clients[i].id)
  }
}
// -> [3]

// 2. enhanced for-loop
for (const client of clients) {
  if (client.hasDevice && client.age > MAX_AGE) {
    elderlyWithDevice.push(client.id)
  }
}
// -> [3]
Enter fullscreen mode Exit fullscreen mode

FP(L) approach:

const olderThan70WithDevice = client => client.age > 70 && client.hasDevice
const getId = client => client.id

let elderlyWithDevice = clients.filter(olderThan70WithDevice).map(getId)

// -> [3]
Enter fullscreen mode Exit fullscreen mode

Benefits of FP revisited

Hopefully you can see the power of having declarative code. When reading the code to understand it (we tend to do that a lot!) we can accept filter(olderThan70WithDevice) and move on, we don't have to dive into this logic to understand what is happening, unless we choose to. Having imperative code on the other hand, we need to understand the logic to move on. Another benefit is by separating the logic of the filter function (predicate) and the map function (transform) to separate functions they can now be reused and tested individually.

Stay DRY with closures

By using closures we can even DRY up our age filter. Lets create a function that takes a number (age) and returns a filter we can use the client. An age filter factory if you like.

We declare a function that takes a number and return a new function that takes a client which returns a boolean.

number -> (client -> boolean)

function filterOlderThan(age) {
  return function (client) {
    return (client.age > age)
  }
}
Enter fullscreen mode Exit fullscreen mode

This can now be used to create new filters.

const isOlderThan70 = filterOlderThan(70)
const isOlderThan80 = filterOlderThan(80)

// use as filter
clients.filter(isOlderThan70).map(getId)
// [1, 3, 4]

clients.filter(isOlderThan80).map(getId)
// [3]

// use in if
if (isOlderThan70(clients[0])) {
  ...
}
Enter fullscreen mode Exit fullscreen mode

For the purpose of this FP introduction I have used simple, trivial even, examples but as code gets more complicated the more relevant the strengths of FP get.

Disclosure: I'm writing this as a humble newbie on the subject, I am not an expert functional programmer. This is my first post and English is my second language.

Read more

The spark for me was this book, https://github.com/getify/Functional-Light-JS

Discussion (2)

Collapse
sizvix profile image
Sizvix

:-/ ...
You made a test with client.hasDevice && and the variable is elderlyWithoutDevice
And the FP version don't test client.hasDevice , so we can't make a comparaison ... :-/

Collapse
sebring profile image
J. G. Sebring Author

Oh, it's actually a mess, yes you are right, can't believe this slipped in. I had a real life version containing much more logic and company specific bits I refactored out for the example. I'll update, my bad.

Forem Open with the Forem app