Function composition in Ruby
We’re now deep into the festive period, and I’ve started to be filled with the Christmas spirit. Perhaps as a result of which, I’ve been playing around with the idea of writing functional code in Ruby… Not because I think this is a good idea, or “the future”, but just because.
In that spirit, I decided to see if I could implement a compose
function in Ruby. I wanted compose
to be a variadic function, which takes one or more unary (single-argument) functions and returns a new function which is the composition of the supplied functions.
For example, given two lambda functions:
addOne = { lambda { |n| n + 1 } }
timesTwo = { lambda { |n| n * 2 } }
I want to have a compose
function, such that:
compose(addOne, timesTwo).call(n) == addOne.call(timesTwo.call(n))
Ignoring the requirement for compose
to be variadic function, a solution for two functions might be:
def compose2(f, g)
lambda { |x| f.call(g.call(x)) }
end
The solution for compose
to be three functions might then be:
def compose3(f, g, h)
lambda { |x| f.call(g.call(h.call(x))) }
end
This reveals an interesting pattern, because another way of defining this might be:
def compose3(f, g, h)
compose2(compose2(f, g), h)
end
This pattern can then be more generally expressed with a reducer:
def compose(*fns)
fns.reduce { |f, g| lambda { |x| f.call(g.call(x)) } }
end
Which now gives us our variadic compose
function in Ruby. Maybe not very useful, but still quite interesting!