DEV Community

Cover image for Functional Programming for the Object-Oriented Developer - Part 1
Patricio Ferraggi
Patricio Ferraggi

Posted on • Edited on

Functional Programming for the Object-Oriented Developer - Part 1

If you are interested in reading this article in Spanish, check out my blog The Developer's Dungeon

Hello friends! It has been some time right?. I apologize if I was absent for a while and left you wanting to continue learning functional programming.
Or you might be thinking, is this guy writing about functional programming again?

NotGoingToHappen

I was working very hard on the redesign of my website and blog.
This article was posted there first, as always, in Spanish
You can check it here, I hope you like it.

But now we can continue this journey, learning functional programming. In my introductory article, we talked a little about basic concepts of FP as:

  • what is a function in mathematical terms
  • what is function composition and why it is important
  • what are pure functions

These concepts are going to be very useful today to continue delving into FP.
If you did not read my previous article you can do it here.

This new part is very practical, tons of JavaScript examples, so let's get to it.


Functions as "First Class Citizens"

WTF? Let's go slowly, this concept means that in JavaScript and functional languages like Haskell or Clojure, functions are a fundamental element of the language, being that way they can be used like any other type of variable.

We can pass functions to other functions as parameters and we can return functions as the product of other functions. A classic example of this is callbacks in JavaScript:

http.get("some/api", params, function(err, data, response) {
  if(!err) {
    // Here would be the code that
    // handle a positive API response
  } else {
    console.log(err)
  }
})
Enter fullscreen mode Exit fullscreen mode

In the previous example, we make a call to an API, and we pass a function as a parameter, we say: "When the call to that API ends, please execute this function". This is possible only because functions are citizens of the first order and we can pass them as a normal parameter. How does this help us? Let's go back to a topic we saw in the previous article.

Another look onto function composition

As we said, composing functions allows us to create much more complex behaviors from small and generic functions.
Now, traditionally function composition in javascript is achieved by executing the function as we see in the following example:

function isBiggerThanThree(value) {
  return value > 3
}

function mapBoolToHumanOutput(value) {
  return value ? "yes": "no"
}

const result = mapBoolToHumanOutput(isBiggerThanThree(3))
Enter fullscreen mode Exit fullscreen mode

Thus we achieve a complex result based on 2 small functions, but is there another way? YES! We can use a help function like the following:

const compose = (...fns) => x => fns.reduceRight ((v, f) => f(v), x)
Enter fullscreen mode Exit fullscreen mode

This function is a classic one of functional languages, most of them already include it in the main language library, JavaScript unfortunately does not, fortunately, libraries like RamdaJs (or any other library that implement the FantasyLand Specification) incorporate the function into JavaScript.
This function simply receives any number of functions as parameters, and as long as it complies with the mathematical rules of composition that we saw in the previous article, it returns a new function that has the behavior of all the previous ones combined. Let's see an example:

function isBiggerThanThree(value) {
  return value > 3
}

function mapBoolToHumanOutput(value) {
  return value ? "yes": "no"
}

const biggerThanThreeAndMapOutput = compose(
  mapBoolToHumanOutput,
  isBiggerThanThree
)

biggerThanThreeAndMapOutput(3)
Enter fullscreen mode Exit fullscreen mode

Isn't this awesome? And what if we also want to log the results?

const biggerThanThreeAndMapOutputAndLogIt = compose(
  console.log,
  mapBoolToHumanOutput,
  isBiggerThanThree
)

biggerThanThreeAndMapOutputAndLogIt(3)
Enter fullscreen mode Exit fullscreen mode

Yes, just like that! function composition and nothing more. Who would say that mathematics was going to be helpful right?
I also know what you're thinking, what's the point of this? Well, there are quite a few:

  1. It allows us to create more readable code without having to concatenate 3 functions one behind the other to obtain a result
  2. It allows us to create this function without having to execute it, we define a new function and we can do what we want with it
  3. Since functions are "First Class Citizens" in JavaScript, we can pass this function to others as parameters, then we can compose different functions at runtime and thus alter the operation of our program according to our needs
  4. Using function composition, we eliminate the need to define intermediate variables, without losing the readability of the code. When executing our composite function, the result is passed from one function to another automatically

Let's continue, there is much to discover 😀

Currying

Sure dude, I like Indian food too but I don't know if it's the right time, don't you think?
No, no, currying is not throwing Curry at everything you can think of (although that doesn't sound too bad ahah)
Currying is a very important concept in functional programming, it is the inverse process to function composition and is defined as follows:

"It is the technique of transforming a function that uses multiple arguments into a sequence of functions that use a single argument"

Let's look at an example to understand it:

// No Currying
function sumTwoValues(x, y) {
  return x + y
}

sumTwoValues(2, 2) // = 4

// With Currying
function sumTwoValues(x) {
  return y => {
    return x + y
  }
}

sumTwoValues(2)(2) // = 4
Enter fullscreen mode Exit fullscreen mode

Damn, I don't want to do this for every function. Well luckily it is not necessary, as with compose, many JavaScript libraries already incorporate this by default using the help function curry of RamdaJs we can do it as follows:

// No Currying
function sumTwoValues(x, y) {
  return x + y
}

sumTwoValues​​(2, 2) // = 4

// With Currying - Using R.curry from RamdaJs

const curryiedSum = R.curry(sumTwoValues)

curryiedSum(2)(2) // = 4
Enter fullscreen mode Exit fullscreen mode

What is the benefit of this you wonder? A little more, we are almost there.

Partial application of a function

Partial application is simply put, to execute a function with fewer arguments than you need and thus creating a new behavior. I don't know if you noticed but when we did Currying we were grabbing a function that has 2 parameters and we passed only one, what happened to the other parameter? let's see.

// Using R.curry de RamdaJs
function sumTwoValues(x, y) {
  return x + y
}

const curryiedSum = R.curry(sumTwoValues)

// curryiedSum is a function that receives a single parameter
// and returns a function that receives the second parameter
// therefore we could do this

const addTen = curryiedSum(10)

// addTen is a new function, which when executed will add 10 to the parameter we choose
// this is known as partial application
addTen(30) // = 40
Enter fullscreen mode Exit fullscreen mode

Let's review what we learned, this "addTen" is a new function, we can do what we want with it, pass it to other parts of the code or compose it with other functions.


As we said before, functional programming is all about functions, with small and simple things, achieving big things without losing expressiveness and adaptability in our software.
Today we cover a series of fundamental and very interesting concepts, key for our trip.

They will allow us to open doors that were previously not possible or that we required immense strength to achieve it.
In the next tutorials, we will continue adding new tools to our belt and using these key elements in new ways. But for now, you can be proud of yourself, if you already start thinking this way in JavaScript, then you will already be doing Functional Programming.

whatifFunctional

If you liked this article, or if you didn't like it, I ask you to let me know in the comments below. If you were left with doubts please also leave a comment so we can make sure everything is clear before moving on to the next topic.

Top comments (0)