Skip to main content

2 posts tagged with "functional programming"

View All Tags

· 3 min read
Samuel Joset

In this post, we'll explain what are higher-order function and explore the how to use the most common of them.

1. What are Higher-Order Functions?

A higher-order function (or a HOC) is a function that can take another function as an argument or return a function as its result.

It is only possible with some programmation languages where functions can be treated like any other value. In these cases we say that functions are first-class citizens in this programming language. For example, there treated as first-class citizens in Javascript. Thanks to that we can create higher-order function.

Some examples of higher-order functions in JavaScript include map, filter, and reduce. These functions take another function as an argument and use it to transform or filter an array.

2. Common Higher-Order Functions

JavaScript has several built-in higher-order functions that are commonly used. A good start to understand and use HOC in our daily coding sessions is to get familiar with the basic HOCs. The most common of them are map, filter and reduce. Let's see what they do and how to use them.

2.1. Map

The map function is used to transform an array by applying a function to each of its elements and returning a new array of the same length with the transformed values. The original array is not modified. Here's an example:

const numbers = [1, 2, 3, 4, 5];

const doubled = numbers.map((num) => num * 2);

console.log(doubled); // [2, 4, 6, 8, 10]

In this example, the map() function is used to double each element in the numbers array and return a new array containing the transformed values.

The powerfull side of this function is that you can easily apply a function to a list of item instead of one. It is way more concise and readable than foreach. And as you may know less code means less place of bugs.

2.2. Filter

The filter() function is used to create a new array that contains only the elements from the original array that pass a given test. An element pass the given test only if the function used returns true:

const numbers = [1, 2, 3, 4, 5];

const evenNumbers = numbers.filter((num) => num % 2 === 0);

console.log(evenNumbers); // [2, 4]

In this example, the filter() function is used to create a new array containing only the even numbers from the numbers array.

2.3. Reduce

The reduce function is used to agragate some or all of the elements of an array into a single value. It takes two arguments: a reducer function and an initial value. The reducer function is applied to each element of the array, accumulating a value that is returned at the end. Here's an example:

const numbers = [1, 2, 3, 4, 5];

const sum = numbers.reduce((acc, curr) => acc + curr, 0);

console.log(sum); // 15

In this example, the reducer function takes two arguments: acc (short for "accumulator") and curr (short for "current"). The acc value starts at 0 and is updated with the sum of each element in the array.

These three HOCs are among the most commonly used in functional programming. When well used and they can significantly simplify your code and improve its readability.

3. Conclusion

Like pure function, understanding and using higher-order functions is an essential aspect of functional programming as we use them in every more advanced concepts.

We have covered some of the most commonly used higher-order functions. They are useful in so many cases that you can use them every day. I personally use them daily.

Once you'll get comfortable with them you will be able to tackle some more advanced functional programming concepts.

· 3 min read
Samuel Joset

Pure functions are a fundamental concept in functional programming, and they play a crucial role in developing high-quality, maintainable code.

The purpose of this article is get familliar to the concept of pure functions.

1. What are Pure Functions?

Pure functions are functions that have the following characteristics:

  • Pure functions always produce the same output given the same input. They have no side effects and do not depend on any external state or global variables.
  • Pure functions have no observable effects outside of their own scope. They do not modify any external state, like changing the value of a variable or updating the DOM.
  • Pure functions are referentially transparent, meaning that they can be replaced with their return value without affecting the behavior of the program.

1.1. Examples of Pure Functions:

// returns the sum of two numbers.
const add = (a, b) => a + b;

// returns the product of two
const multiply = (a, b) => a * b;

// returns a greeting message
const greet = (name) => `Hello, ${name}!`;

As you can see, each of these functions takes input and returns output without modifying any external state.

1.2. Pure VS Impure Functions:

In contrast to pure functions, impure functions have side effects or depend on external state, which can make them less reliable and harder to reason about. Here is an example of an impure function:

let counter = 0;

/**
* @function increment - Impure function that increments a counter and returns its value.
* @returns {number} - The updated value of the counter.
*/
const increment = () => {
counter++;
return counter;
};

The function increment modifies the external state of the counter variable each time it is called, making it impure. It is also not referentially transparent, as replacing the function with its return value would not increase the counter.

2. Benefits of Pure Functions

Overall, the benefits of pure functions make them a valuable tool for writing maintainable, testable, and reusable code. By striving to write pure functions whenever possible, we can build more reliable and robust applications.

2.1. Predictability and Reliability

Since pure functions always produce the same output for the same input, they are predictable and reliable. This makes it easier to reason about the behavior of the code, reducing the risk of introducing bugs.

2.2. Testability

Pure functions are also easier to test than impure functions. Since they do not depend on external state, we can pass any input we want and expect the same output every time. This makes it easy to write automated tests to ensure that the function works as expected. Here's an example using the multiply function:

/**
* Returns the result of multiplying two numbers
*/
const multiply = (a, b) => a * b;


// Tests using jest
describe('multiply', () => {
it('should return the product of two numbers', () => {
expect(multiply(2, 3)).toBe(6);
expect(multiply(-1, 5)).toBe(-5);
expect(multiply(0, 10)).toBe(0);
expect(multiply(2.5, 4)).toBe(10);
});
});

These tests ensure that the multiply function returns the correct result for a variety of inputs. By testing the function in isolation, we can be confident that any errors are the result of a problem with the function itself, rather than external factors.

2.3. Reusability and Composability

Pure functions are also highly reusable and composable. Since they do not depend on external state, they can be used in a wide variety of contexts without fear of unexpected side effects.

3. Conclusion

Pure functions are an important concept in functional programming and can offer numerous benefits to the development process. By creating functions that are deterministic, reliable, and easy to reason about, developers can write high-quality, maintainable code that is less error-prone and more performant.

By creating pure functions, developers can also take advantage of features like referential transparency and immutability, which can improve the readability and efficiency of their code. Additionally, the testability of pure functions allows developers to catch errors early in the development process, reducing the time and effort required for debugging.

Overall, understanding and utilizing pure functions is a valuable skill for any developer.