>A typical situation when coding is calculating some value and assigning it to a local variable in order to avoid re-computing. I have been thinking about a solution to better control such local variables created just to be used (multiple-times) in a single ruby expression.
Here is an example that computes the roots of a quadratic formula. Note that a local variable called ‘discriminant’ is created just to be used in that last line.
def root1( coef1, coef2, coef3, discr )
( -coef2 + Math.sqrt(discriminant) ) / ( 4 * coef1 * coef3 )
end
def root2( coef1, coef2, coef3, discr )
( -coef2 - Math.sqrt(discriminant) ) / ( 4 * coef1 * coef3 )
end
def find_quadratic_roots( a, b, c )
discriminant = b * b - 4 * a * c
[ root1(a, b, c, discriminant), root2(a, b, c, discriminant) ]
end
What I’d like to do is to merge the last two lines in this method, and not create the local variable discriminant. It is presumably not very apparent why I’d avoid creating the local variable, but in methods with more than one such local variables, the method get unnecessarily long.
One way of doing it is by using a define-use-and-forget lambda function:
def find_quadratic_roots( a, b, c )
lambda { |discr| [ root1(a, b, c, discr), root2(a, b, c, discr) ] }[ b * b - 4 * a * c ]
end
What I don’t like about this approach is that we are creating a Proc object, which might be expensive (or not, actually I need to check ). Furthermore, the computation for ‘discr’ follows its use, which requires one to go back and forth when reading this line.
Another way is making use of using the solution described in this blog article. The problem is that it requires you to define a new method ‘let’, which you then use in your code. Adding such general-purpose code fragments to multi-developer projects is not always that easy.
Here is how I prefer to write it, using a tap trick:
def find_quadratic_roots( a, b, c )
[ b * b - 4 * a * c ].tap { |rv| rv.replace [ root1(a, b, c, discr), root2(a, b, c, discr) ] }
end
Let me know if you have a better solution.
Happy coding..
–inchotus