Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call a block method on an iterator: each.magic.collect { ... }

Tags:

iterator

ruby

I have a class with a custom each-method:

class CurseArray < Array
    def each_safe
        each do |element|
            unless element =~ /bad/
                yield element
            end
        end
    end 
end

And want to call different block methods, like "collect" or "inject" on those iterated elements. For example:

curse_array.each_safe.magic.collect {|element| "#{element} is a nice sentence."}

I know there is a specific function (which I called "magic" here) to do this, but I've forgotten. Please help! :-)

like image 202
blinry Avatar asked Feb 28 '23 06:02

blinry


1 Answers

If a method yields you will need to pass it a block. There is no way define a block that automatically passes itself.

Closest I can get to your spec is this:

def magic(meth)
  to_enum(meth)
end

def test
  yield 1 
  yield 2
end

magic(:test).to_a
# returns: [1,2]

The cleanest way of implementing your request is probably:

class MyArray < Array 
  def each_safe 
    return to_enum :each_safe unless block_given? 
    each{|item| yield item unless item =~ /bad/}
  end 
end

a = MyArray.new 
a << "good"; a << "bad" 
a.each_safe.to_a
# returns ["good"] 
like image 164
Sam Saffron Avatar answered Mar 01 '23 20:03

Sam Saffron