Loops using fold. In functional programming we do not use almost any for
or while
. Instead of writing loops using imperative instructions, in functional programming you have a series of functions that allows you to loop over collections.
The most flexible and used of these functions is called fold
(foldl
, foldLeft
, reduce
).
In this article, we are going to learn how to implement loops using fold in functional programming.
Practical Functional Programming step by step is a series in which we are going to uncover the principles of functional programming and effective coding one small piece at the time.
Starting from a complete code example, we are going to learn step by step what makes a good functional code and what are the benefits of applying a functional programming paradigm to your codebase.
Why you do not need loops
If you are used to write imperative code, you may consider for
, while
, forEach
as one of the main constructs in your codebase. These constructs are the first one to which you are introduced when you start learning about code and programming.
Nonetheless, these constructs are not generally safe nor required. They relay on you to implement all the details behind your algorithm in an imperative manner.
When you use a for
loop, you must take care of initialising all the variables, updating their values every cycle, paying attention to every detail. This makes you code difficult to read and error prone.
Remember then, you do not need loops. Not at all. If you are not convinced, take a look here for an extensive dive deep into the subject.
Loops using fold in Functional Programming
What to do instead of loops?
There are be many ways of implementing loops. In this article we are going to explore the fold
function.
The fold
function works exactly like a for
loop over a collection. It takes the elements of the collection one by one and lets you do some operation on these values.
Let's look at our code example:
Map<String, int> buildmap(String str) => str.split('').foldLeft(
<String, int>{},
(acc, x) => {
...acc,
x: (acc[x] ?? 0) + 1,
},
);
In the buildmap
function, we are using foldLeft
. This function allows us to cycle over all the letters of the source string and accumulate them in one final value.
The first parameter is the initial value of the accumulator (and empty Map
). Then, for each element in the collection, foldLeft
will call the second function provided, passing the accumulator and the values in the collection.
By using foldLeft, we convert a List
into a Map
. This same function could be rewritten imperatively as follows:
Map<String, int> buildmap(String str) {
var acc = <String, int>{};
var list = str.split('');
for (var i = 0; i < list.length; ++i) {
final x = list[i];
acc[x] = (acc[x] ?? 0) + 1;
}
return acc;
}
As you can see, using imperative programming you are required to take care of every detail in the implementation. Using fold
instead, you only need to provide what's necessary; Namely the initial value and the accumulator function!
You should now have a more clear idea of why loops are (generally) bad and how you can do without them. fold
can be used to implement a great variety of other functions (map
, zip
, filter
). Once you understand how fold works, you have a powerful tool at your disposal!
See you on Part 5!