Search code examples
rubyarraysblockproc

Adding a method to the Array class via a proc/block?


I'm trying to add extra functionality in the Array class to take in a block. I think I've mostly got that down, however, I'm not sure of the syntax I want to use when calling the method uses a .to_proc / & casting for predefined methods (eg. .odd? ).

I have the following code:

class Array 

  def keep
    each do |user_array_element|
      user_array_element
      if yield(user_array_element) == true 
        kept_elements ||= []
        kept_elements << user_array_element
      end
    end
  end
end

Trying to get the following test to pass:

assert_equal [1, 3], [1, 2, 3].keep(&:odd?)

Solution

  • Your test isn't passing because each returns the enumerable that it is called upon. To fix, change your definition like so:

    class Array 
      def keep
        [].tap do |kept_elements|
          self.each do |element|
            kept_elements << element if (yield(element) == true)
          end
        end # will return kept_elements
      end
    end
    

    An alternative is using each_with_object:

    class Array 
      def keep
        self.each_with_object([]) do |element, kept_elements|           
          kept_elements << element if (yield(element) == true)
        end # will return kept_elements
      end
    end
    

    The code above is just to show you how to get your own code to work. But essentially, you're writing a method for what select already does (except that it selects any element for which the block doesn't yield nil or false).