Trying to understand a code example (pg 110, cart.rb)
Scott Gardner
6 posts
|
The following section of code (excerpted from page 110 depot_g/app/models/cart.rb line 2 in the book, but I’ve included relevant setup code) has_thrown_me_for :a => :loop…
Here’s how I understand it: Can someone please confirm that I have this correct? Presuming yes, I still do not understand how the block, which resolves true or false, knows to return the actual item object when a true condition occurs. Thanks! |
Sam Ruby
36 posts
|
Note that this only occurs when the Cart itself is initialized. After that point, @items can change.
Yes.
More precisely, each item in the @items array is passed to the block until an item is found for which the block evaluates to true.
This is correct.
It doesn’t. The block is a procedure. It is passed as a parameter to the find method. It is an object with a call method. This means that the caller (in this case, the find method) can call it as many times at it likes, with whatever parameters it likes. And that is exactly what the find method does. It calls the block repeatedly with each successive item in the array until it finds one which causes the block to evaluate true. If this occurs, the find method knows which item it passed to the block, and it simply returns that item. If, instead, it exhausts the list, it simply returns nil instead. |
Scott Gardner
6 posts
|
Thanks for the detailed explanation. I am really just trying to put a handle on this because I realize it’s a key and common usage in Ruby/Rails. I think, for now, I will just have to rely on rote memory of how this works. Also, can you confirm/correct your statement that this block is in fact an object? According to this explanation on rubylearning.com, a block is not an object unless it is converted to a Proc (e.g., using lambda). |
Sam Ruby
36 posts
|
The block is automatically converted to a Proc, which is an object. It may help to play with this yourself by adding your own find method to the Array class, thus:
class Array
def my_find &block
puts "block class = #{block.class}"
for item in self
puts "testing item: #{item}"
if block.call(item) == true
return item
end
end
return false
end
end
data = [1, 2, 3, 4, 5]
puts "scanning for a three"
result = data.my_find {|i| i == 3}
puts "result: #{result}"
|
Scott Gardner
6 posts
|
That really helped, thanks! |
5 posts, 2 voices
