using print inside def having yield statement

110 Views Asked by At

I am trying to print inside a function. The function is used for invoking a block. But I don't see the print happening in the function definition. Please shed a light on this. Basically I am not clear with the control flow.

def find_all 
   matching_items = [] 

   self.each do |item|

      if yield(item)
         puts "after yield" #print not happening
         matching_items << item
      end
   end

   matching_items

end

p ['a', 'b','c','c'].find_all { |item| 
  if item == 'a'
     true 
  end   
  } 
2

There are 2 best solutions below

0
On BEST ANSWER

If you are trying to re-open the class Array then, this is how you can do it

class Array
  def find_all(matching_items = [])
    self.each do |item|
      if yield(item)
        puts "after yield" #print not happening
        matching_items << item
      end
    end
    matching_items
  end
end

p ['a', 'b', 'c', 'c'].find_all { |item|
    if item == 'a'
      true
    end
  }

Output

after yield
["a"]
1
On

If your code is exactly as written, you are defining and independent method find_all defined on main. When you type [1,2,3,4].find_all, you are calling the find_all method on Array, which is defined in the Enumerable method. So you are not calling your method at all.

What you are probably trying to do is

class Array
  def find_all
    ...
  end
end

This way, [1,2,3,4].find_all will call this method.

However, note that this is probably a bad idea: you're overriding a core method that in a class that isn't yours, so that could have consequences in other code that you are not able to anticipate if any other code uses the find_all method.

What you might try instead is to define a method that takes the array in as an argument. You might move this to a module, but for now:

def find_all(array)
  matching_items = [] 

   array.each do |item|

      if yield(item)
         puts "after yield" #print not happening
         matching_items << item
      end
   end

   matching_items

end

Of course, this is basically what Enumerable#find_all already does, but less efficiently: so perhaps this is just an academic exercise, in which case, great!, but otherwise, why not just use the existing method?