Mar 28, 2019

Say goodbye to loops with ‘reduce’ ????

If you’re starting with functional programming and don’t know where to continue after map and filter, go with reduce.

–Do you insist on using the image of the cat? –Yes, I do. Reflects the essence of functional programming. Source: https://farm6.staticflickr.com/5185/5619954191_565779cf5d_b.jpg

Reduce is the holy grail of versatility when it comes to processing objects and lists. Its properties allow you to implement practically anything:

– you can determine your initial value

– you control the output type

– it walks through all elements

This means you get to control what goes in, what goes out and what is inside at all times. With that in mind, you can do whatever pure operation you like during the iteration as it is still you controlling the output. For example, here is how to implement filter using reduce:

// JS
const filter = (fn, list) =>
  list.reduce((acc, next) => (fn(next) ? 
acc.concat(next) : acc), []);
// Haskellfilter’ :: (a -> Bool) -> [a] -> [a]
filter’ fn = foldr (\x xs -> if fn x then x:xs else xs) []

The same can be done for map:

// JSconst map = (fn, list) =>
  list.reduce((acc, next) => acc.concat(fn(next)), 
[]);
// Haskellmap’ :: (a -> b) -> [a] -> [b]
map’ fn = foldr (\x xs -> fn x : xs) []

Keep in mind that reduce can produce any value type, so you can do iterations requiring you to remember some intermediate value. For example, if we wanted to select lines placed in between two other lines, we could have an object of { output: “”, inbetween: false }. Then:

  • if inbetween and not end line, concat to output
  • if inbetweenand end line, return output and set inbetween to false
  • if not inbetweenand start line, set inbetweento true
  • if not inbetween and not start line, just return accumulator

Just take the output property when finished and you’re done.

So next time you would want to use a for loop, go for reduce instead! If it is the preferred way in your language, of course.

Search
Share
Featured articles
Generating SwiftUI snapshot tests with Swift macros
Don’t Fix Bad Data, Do This Instead