Today, I was working with some ruby code that had to find the first product in one of the current contexts. Here is the code:
This code tries to find the first product in the current contexts in the order they are defined. However, the above code has a tiny bug. Can you figure out what it is?
In cases where there are no products in any of the contexts this function
returns the array
[1, 2, 3] instead of returning
returns the array and in the case where we don’t find the product we don’t
We can easily fix this by adding an extra return at the end of the function.
The fix is awkward, let us see if we can improve this.
We could use
.map to find a product for every context and return the first not
nil record like so:
This looks much cleaner! And it doesn’t have the previous bug either. However, this code is not efficient, we want to return the first product we find for all the contexts, and the above code always looks in all contexts even if it finds a product for the first context. We need to be lazy!
.lazy on an enumerable gives you a lazy enumerator and the neat thing
about that is it only executes the chain of functions as many times as needed.
Here is a short example which demonstrates its use:
As you can see from the above example, the lazy enumerator executes only as many times as necessary. Here is another example from the ruby docs, to drive the point home:
Now applying this to our code is pretty straightforward, we just need to add a
#.lazy before we map and we are all set!
Ah, nice functional ruby!