This is a multi-part series on Refactoring to Functional Programming
In this part let’s pick up some more primitives of functional programming and see how we can use them. We’re going to expand the previous list of albums to also include track information
We’re going to solve two different exercises this time:
- Get a list of albums and their total duration.
- Get a list of tracks that are shorter than a certain length, along with the corresponding album title.
To get a list of albums and their total duration, we’ll go for the simplest approach, using some of the primitives we picked up in the previous part.
reducing to a single value
What we’re doing in the previous code is iterating through the list of tracks and summing them up. As expected, there’s a function for that: reduce. Reduce takes a list of items and returns a single value, applying a specific operation to the list.
Knowing this, we can refactor the code to use reduce.
reduce versus fold
Kotlin also provides a very commonly used function named fold which does the same thing as reduce. The difference between the two is that fold takes an explicit initial value, whereas reduce uses the first element from the list as the initial value.
Dealing with trees
Up to now, we’ve used forEach, map, filter and reduce to perform operations on lists. The problem with trying to find a list of tracks that meet a certain criteria is that this list is a list inside another list, i.e. we have a tree, albeit a small one. Filtering the original list is not going to work since the information to filter is on a branch. We therefore need to filter out based on the branch.
Here’s a first attempt
What we’re doing is iterating through the list of albums, and then for each one, filtering out those that match a certain criteria. On each iteration we hold a reference using a closure to the current album, and then add those matching the criteria as a new pair to the result.
Once again we can avoid some of this manual work and delegate it to a function named flatMap that takes a list, applies a transformation to each item and returns a new list with these items.
With that, we can refactor the previous code to
There’s a more generic version of flatMap, named flatMapTo which allows us to specify the resulting collection.
Other constructs as they come
In addition to filtering results, we can also find out if an item on the list matches a certain predicate with any, or if all items match it with all and last but not least find the first item that matches it with find.
We can also group items of a list or zip two lists (combine items from each list into pairs into a new list) as well as perform a few more basic operations on lists. Hopefully with these constructs we’ll have enough to solve problems.
Until next time.