# Filtering blocks

**URL:** <https://www.ruby-forum.com/t/filtering-blocks/155136>\
**Category:** Ruby\
**Created:** [December 8, 2008, 4:14pm UTC](https://www.ruby-forum.com/t/filtering-blocks/155136 "2008-12-08T16:14:16Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![maartenm](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/5e9695/32.png) [@maartenm](https://www.ruby-forum.com/u/maartenm)\
**Post date:** [December 8, 2008, 4:14pm UTC](https://www.ruby-forum.com/t/filtering-blocks/155136/1 "2008-12-08T16:14:16Z")

</div>

Is it possible to filter blocks, online, in an elegant way?

for instance if I have the block

class Integer  
def divisors  
(1…self).each{ |i| yield i if self % i == 0 }  
end  
end

and I want to pass this block through an ‘online’ filter.

I want to do something elegant like  
10.divisors.odd{ |n| puts n }

# instead of

10.divisors{ |n| puts n if n.odd? } #, which is pretty much the same as  
10.divisors{ |n| yield n if n.odd? }{|n| puts n}

I suppose it’s not possible at all to treat a block as an object in this  
manner?

If so, suppose I want to use a generic filter that takes a block and a  
condition as its arguments, and returns the block of each elements for  
which a condition is fulfilled?

# pseudo

def filter (block, condition)  
block do |s|  
yield s if s.condition  
end  
end

How would I do anything like this, without using arrays as inbetweens?  
Am I again trying to treat blocks wrongly as objects, is it at all  
possible to ‘operate’ through them in this way?  
I’m new to ruby so this might be a bit stupid. I was just experimenting  
and couldn’t find an elegent, modular manner of filtering blocks  
run-time in a ‘chain-like’ manner, without needlessly compressing them  
to arrays in between.

I got this when googling, btw: [www.rubyfilter.com](http://www.rubyfilter.com) 🙂

---

<div class="post-metadata">

**Author:** ![maartenm](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/5e9695/32.png) [@maartenm](https://www.ruby-forum.com/u/maartenm)\
**Post date:** [December 8, 2008, 5:35pm UTC](https://www.ruby-forum.com/t/filtering-blocks/155136/2 "2008-12-08T17:35:19Z")

</div>

Hm, I think the problem is not to filter a block (that’s also possible,  
because in ruby blocks are also objects of the class Proc). You want to  
filter an Enumeration. Therefore you could use the class Enumerator.

require “enumerator”  
class Integer  
def odds()  
if block\_given? then  
1.upto(self) do |number| yield number if number % 2 == 1 end  
else  
Enumerable::Enumerator.new(self, :odds)  
end  
end  
def evens()  
if block\_given? then  
1.upto(self) do |number| yield number if number % 2 == 0 end  
else  
Enumerable::Enumerator.new(self, :even)  
end  
end  
end

5.odds.each do |number| puts number end

# =\> 1, 3, 5

5.odds.any? do |number| number % 3 == 0 end

# =\> true

And of course you can add more “filters” by extending the Enumerator  
class, or better, a subclass of Enumerator which handles only with  
Integers.

require “enumerator”  
class Integer  
def odds()  
if block\_given? then  
1.upto(self) do |number| yield number if number % 2 == 1 end  
else  
Enumerable::Enumerator::Integer.new(self, :odds)  
end  
end  
def evens()  
if block\_given? then  
1.upto(self) do |number| yield number if number % 2 == 0 end  
else  
Enumerable::Enumerator::Integer.new(self, :even)  
end  
end  
end  
module Enumerable  
class Enumerator  
class Integer \< Enumerator

```
  def prime
    if block_given? then
      each do |number|
        # primitive prime algorithm
        yield(number) unless (2..Math.sqrt(number)).any? do |i|
          number % i == 0
        end
      end
    else
      Enumerable::Enumerator.new(self, :prime)
    end
  end

  def odds
    if block_given? then
      each do |number| yield number if number % 2 == 1 end
    else
      Enumerable::Enumerator.new(self, :odds)
    end
  end

  def evens
    if block_given? then
      each do |number| yield number if number % 2 == 0 end
    else
      Enumerable::Enumerator.new(self, :evens)
    end
  end
end

```

end  
end

12.odds.prime.each {|x| p x}
