Here's what I'm trying to refactor:
items.each_with_index do |item, ndx|
if side == :left
condition = ndx < max
else
condition = ndx >= max
end
result_items << item if condition
end
I'd like to be able to move that if/else/end outside the block, since the value of side never changes inside the block. Since the only thing changing based on the value of side is the operator, I'd like to be able to do something like:
if side == :left
oper = <
else
oper = >=
end
items.each_with_index do |item, ndx|
result_items << item if ndx oper max
end
But of course, that won't work because of the syntax.
Is there anyway to store an operator, or a better way to accomplish what I'm after here?
Operators are just methods:
ndx.public_send(:<=, max)
Is the same as
ndx <= max
So outside the loop set oper to the symbol for the desired operator and inside
result_items << item if ndx.public_send(oper, max)
( you'll have to use send rather than public_send if you're still stuck on 1.8)
Check out "proc" and "lambda". They enable you to hold a reference to, letssay, a anonymous function:
[4] pry(main)> func = proc {|left, right| left < right}
=> #<Proc:0x34c83c0@(pry):4>
[5] pry(main)> func.call(4,5)
=> true
[6] pry(main)> func.call(5,2)
=> false
Note that the 'proc' expects a "block" to be passed, and that block will be later "call"ed with given params. This is the same syntax as if you'd use a map or each - that's all blocks there. proc just returns you that block instead of invoking it.
So, your code can look similar to:
if side == :left
oper = proc{|a,b| a<b}
else
oper = proc{|a,b| a>=b}
end
items.each_with_index do |item, ndx|
result_items << item if oper.call(ndx, max)
end
I've not checked that code, can have some typos.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With