Abusing Reduce

As someone who enjoys functional programming languages (ruby, scala, javascript) one of my most used commands is reduce. The canonical example of reduce is summing a bunch of numbers such as

[1,2,3].reduce(function(sum, number) {
	 return sum+number

or elegantly in ruby


which would produce 6

However, I see reduce as more of a function you can use to build other functions from. For example, I recently wanted to write my own version rubys .any? which takes an array and returns true if any value in the array returns true. How could I write this as a reduce?

Well, there are a few interesting things to note about the reduce function. For one, in the canonical example, sum starts out as the first value of the array and number as the second. However you can override this by passing an initial value such as

[1,2,3].reduce(0) {|sum,number| sum+number}
# => 6

[1,2,3].reduce(5) {|sum,number| sum+number}
# => 11

Secondly, `sum` becomes the return value of the previous interation, knowing these two facts I could write something like this

[1,2,3,4,3,2,1].reduce(false) do |result, num|
	num > 3 || result

For values 1-3 we can see that we’ll have false || false which evaluates to false of course, but for 4, we’ll have true || false, which evaluates to true.

On the next interation we have false || true which evaluates to true and thus our any? like function will correctly return true.

Of course we can make this more general by allowing in to take a predicate function like so

def any?(ary)
    ary.reduce(false) do |result, input|
        yield input || result

any?([1,2,3]) do |value|
    value > 6

Which of course could be optimized by checking that a block was passed (or defaulting a truth test of each item). What happens if someone passes an empty array however?

Well this is where the final interesting thing about reduce comes in, if you pass an empty array, the initial value is returned, and thus any? on an empty array returns false

Now these examples aren’t very exciting I’m sure, but I hope you can see how you could build interesting functions on top of reduce!