lambda is used in this example in both the compose and the hydrate methods. What does lambda do here?
def compose *lambdas
if lambdas.empty?
lambda { nil }
elsif lambdas.size == 1
lambdas.first
else
lambda do |n|
lambdas.first.call(compose(*lambdas[1..-1]).call(n))
end
end
end
def hydrate(modulus, printable_form)
i = 0
lambda do |n|
(i = (i + 1) % modulus) == 0 && printable_form || n
end
end
print(((1..100).map
&compose(
hydrate(15, 'Watermelon'),
hydrate(5, 'Melon'),
hydrate(3, 'Water'))).join(' '))
My second question is – what is the need for the ampersand in front of the word compose?
The function
composetakes a list of functions and returns a newly allocated function that is the composition of all the functions on the list. It’s been written to treat the empty list rather oddly; it may be that the first case should be ignored. (Normally composing the empty list of functions should produce the identity function, but that’s not what your example does. I would have expectedas the base case.)
It’s necessary to use a
lambdain order to create a new function You see that in the recursive case in compose: thelambdacreates a new function which when givennreturns the result of calling the composition of the remaining functions, then finally applies the first function. This is not good code to emulate, as the recursion over the list of functions is repeated every time the composition is called. In the example:Creating the composition of functions uses constant time and space
Applying the composition of functions costs linear time and space
Whereas if the code were written properly
Creating the composition of functions should cost linear time and space
Applying the composition of functions should cost linear time and should require no allocations (zero space)
Unfortunately I don’t know enough Ruby to write for you an example of
composethe way it ought to be done. But others will.