# Enumerable ObjectSpace (#222)

**URL:** <https://www.ruby-forum.com/t/enumerable-objectspace-222/177827>\
**Category:** Ruby\
**Created:** [October 24, 2009, 7:44pm UTC](https://www.ruby-forum.com/t/enumerable-objectspace-222/177827 "2009-10-24T19:44:53Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![danmcb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/13edae/32.png) [@danmcb](https://www.ruby-forum.com/u/danmcb)\
**Post date:** [October 24, 2009, 7:44pm UTC](https://www.ruby-forum.com/t/enumerable-objectspace-222/177827/1 "2009-10-24T19:44:53Z")

</div>

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

The three rules of Ruby Q.:

1. Please do not post any solutions or spoiler discussion for this  
quiz until 48 hours have elapsed from the time this message was  
sent.

2. Support Ruby Q. by submitting ideas and responses  
as often as you can.

3. Enjoy!

Suggestion: A [QUIZ] in the subject of emails about the problem  
helps everyone on Ruby T. follow the discussion. Please reply to  
the original quiz message, if you can.

* * *

RSS Feed: [http://rubyquiz.strd6.com/quizzes.rss](http://rubyquiz.strd6.com/quizzes.rss)

Suggestions?: [http://rubyquiz.strd6.com/suggestions](http://rubyquiz.strd6.com/suggestions)

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

## Enumerable ObjectSpace (#222)

Kaixo Rubyists,

This week’s quiz was suggested by Trans[1](http://rubyworks.github.com).

ObjectSpace has the method #each\_object. I’ve always wanted to alias  
that to #each and make ObjectSpace Enumerable. But there’s a catch,  
#each\_object takes an argument and Enumerable does not pass arguments  
on to the #each method. So how does one resolve this issue? What’s the  
easiest way to make ObjectSpace Enumerable?

One could always take the brute force approach and completely  
re-implement Enumerable module to pass along the arguments. But I’m  
hoping there are much more elegant solutions to be had.

Have fun!

---

<div class="post-metadata">

**Author:** ![danmcb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/13edae/32.png) [@danmcb](https://www.ruby-forum.com/u/danmcb)\
**Post date:** [October 27, 2009, 12:23am UTC](https://www.ruby-forum.com/t/enumerable-objectspace-222/177827/2 "2009-10-27T00:23:46Z")

</div>

> easiest way to make ObjectSpace Enumerable?
> 
> One could always take the brute force approach and completely  
> re-implement Enumerable module to pass along the arguments. But I’m  
> hoping there are much more elegant solutions to be had.

There is probably something better to be had using reflection and method  
generation, but here’s one stab:

class \<\< ObjectSpace  
def method\_missing(sym, _args, &block)  
mod = args.first.is\_a?(Module) ? args.shift : nil  
enum = enum\_for(_[:each\_object, mod].compact)  
enum. **send** (sym, \*args, &block)  
end  
end

# e.g. puts ObjectSpace.map(Class) { |c| c.name }

---

<div class="post-metadata">

**Author:** ![danmcb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/13edae/32.png) [@danmcb](https://www.ruby-forum.com/u/danmcb)\
**Post date:** [October 27, 2009, 9:10am UTC](https://www.ruby-forum.com/t/enumerable-objectspace-222/177827/3 "2009-10-27T09:10:34Z")

</div>

On Saturday 24 October 2009, Daniel M. wrote:

> |on to the #each method. So how does one resolve this issue? What’s the  
> |easiest way to make ObjectSpace Enumerable?  
> |  
> |One could always take the brute force approach and completely  
> |re-implement Enumerable module to pass along the arguments. But I’m  
> |hoping there are much more elegant solutions to be had.  
> |  
> |Have fun!  
> |  
> |  
> |[1]: [http://rubyworks.github.com](http://rubyworks.github.com)

Here’s my solution. It uses an instance variable to keep trace of the  
argument  
given to the enumerable method.

In more detail, here’s how it worsk: after extending Enumerable, in  
redefines  
each method added by it allowing any number of arguments (indeed, all  
that is  
needed is to add one argument. I believe it can be done that way but I  
don’t  
think it’s worth the effort). The first argument is then removed from  
the  
array and inserted at the end of the array contained in the  
@\_\_chosen\_class  
instance variable (which is created if it doesn’t already exist). Then,  
super  
is called, passing it the new argument list (that is, the one with the  
first  
argument removed) and the block.

The each method is then defined to either accept one argument, so that  
you can  
do

ObjectSpace.each(Array){…}

or to use the last element of @\_\_chosen\_class.

The reason to store the class in an array is to allow nested calls, that  
is  
something like this:

ObjectSpace.select(cls1) do |o|  
…  
ObjectSpace.any?(cls2){…}  
…  
end

When ObjectSpace.any? is called, it’ll push cls2 at the end of  
@\_\_chosen\_class, so that its each will use that class, while each for  
the  
outer block will use cls1. I enclosed the call to super in a  
begin/ensure  
clause to be sure that the class pushed in the array is removed at the  
end of  
the method call.

module ObjectSpace

methods = Enumerable.instance\_methods - self.public\_methods

extend Enumerable

methods.each do |m|

```
instance_eval <<-STR

  def #{m} *args, &blk
    @__chosen_class ||= []
    @__chosen_class << args.shift
    begin super *args, &blk
    ensure @__chosen_class.pop
    end
  end

STR

```

end

def self.each cls = nil  
each\_object(cls || @\_\_chosen\_class[-1]){|o| yield o}  
end

end

Stefano

---

<div class="post-metadata">

**Author:** ![danmcb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/13edae/32.png) [@danmcb](https://www.ruby-forum.com/u/danmcb)\
**Post date:** [October 27, 2009, 11:16am UTC](https://www.ruby-forum.com/t/enumerable-objectspace-222/177827/4 "2009-10-27T11:16:27Z")

</div>

2009/10/27 Stefano C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> On Saturday 24 October 2009, Daniel M. wrote:  
> Here’s my solution. It uses an instance variable to keep trace of the argument  
> given to the enumerable method.

Instance variables are not thread safe. I am using a thread local  
instead:

#! ruby19

# CODE

class \<\<ObjectSpace  
include Enumerable

def arg(a, &b)  
stack = Thread.current[:_os\_arg_] ||= []  
stack.push a

```
begin
  instance_eval(&b)
ensure
  stack.pop
end

```

end

def each(&b)  
a = ((Thread.current[:_os\_arg_].last || Object) rescue Object)  
each\_object(a, &b)  
self  
end  
end

# TEST

Foo = Struct.new :x  
foos = (1…10).map {|i| Foo.new i}

result\_test = ObjectSpace.arg Foo do  
p map {|x| x.inspect}

ObjectSpace.arg String do  
string\_count = inject(0) do |sum, o|  
raise “no string” unless String === o  
sum + 1  
end

```
puts "Nested String count: #{string_count}"

```

end

map {|x| “rt #{x.inspect}”}  
end

p result\_test

Thread.new do  
p ObjectSpace.inject(0) {|sum,| sum + 1}  
end.join

ObjectSpace.arg Foo do  
p map {|x| x.class}  
end

Cheers

robert

---

<div class="post-metadata">

**Author:** ![danmcb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/13edae/32.png) [@danmcb](https://www.ruby-forum.com/u/danmcb)\
**Post date:** [October 27, 2009, 11:22am UTC](https://www.ruby-forum.com/t/enumerable-objectspace-222/177827/5 "2009-10-27T11:22:18Z")

</div>

On Tuesday 27 October 2009, Robert K. wrote:

> |Instance variables are not thread safe.  
> |

Yes, I was aware of this problem but forgot to mention it in my  
solution.

Stefano

---

<div class="post-metadata">

**Author:** ![danmcb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/13edae/32.png) [@danmcb](https://www.ruby-forum.com/u/danmcb)\
**Post date:** [October 28, 2009, 10:14am UTC](https://www.ruby-forum.com/t/enumerable-objectspace-222/177827/6 "2009-10-28T10:14:00Z")

</div>

Hi, here is my try:

module ObjectSpace  
extend Enumerable

```
def each(mod = nil, &block)
    if block_given?
        if mod.is_a? Module
            each_object(mod) { |o| block.call(o) }
        else
            each_object { |o| block.call(o) }
        end
    else
        to_enum
    end
end
module_function :each

(Enumerable.instance_methods-[:to_enum]).select { |m|

```

self.method(m).arity == 0 }.each { |m|  
instance\_eval \<\<-STR  
def #{m}(mod = nil, &block)  
if mod.is\_a? Module  
objects = to\_enum.select { |o| o.is\_a? mod }  
else  
objects = to\_enum  
end  
objects.send(:#{m}, &block)  
end  
STR  
}  
end

Some tests:

p ObjectSpace.each #=\> #\<Enumerator: ObjectSpace:each\>  
p ObjectSpace.map(Numeric) { |o| o } #=\> [2.718281828459045,  
3.141592653589793, …]

p ObjectSpace.map(Class) { |c| c.name }.select { |o| o.to\_s[0]\<“E” } #=\>  
[“Complex”, “Binding”, …]  
p ObjectSpace.select(Class) { |o| o.to\_s[0]\<“E” }.map { |c| c.name } #=\>  
[“Complex”, “Binding”, …]

I’m wondering which method should implement an arg. For this I used:  
(Enumerable.instance\_methods-[:to\_enum]).select { |m|  
self.method(m).arity  
== 0 }  
#=\> [:to\_a, :sort, :sort\_by, :find\_all, :select, :reject, :collect,  
:map,  
:partition, :group\_by, :all?, :any?, :one?, :none?, :min, :max, :minmax,  
:min\_by, :max\_by, :minmax\_by, :reverse\_each, :take\_while, :drop\_while]

I think the main interest is for each and map, maybe select because it  
looks  
nice.

For the others, it seem more clear to me to do: ObjectSpace.select {|o|  
o.is\_a? mod}

Something I don’t understand is why it seem impossible to modify each if  
Enumerable is included

Cheers

---

<div class="post-metadata">

**Author:** ![danmcb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/13edae/32.png) [@danmcb](https://www.ruby-forum.com/u/danmcb)\
**Post date:** [November 1, 2009, 9:27pm UTC](https://www.ruby-forum.com/t/enumerable-objectspace-222/177827/7 "2009-11-01T21:27:02Z")

</div>

On Oct 28, 4:13 am, Benoit D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Something I don’t understand is why it seem impossible to modify each if  
> Enumerable is included

Not sure what you mean. Could you explain further?

---

<div class="post-metadata">

**Author:** ![danmcb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/13edae/32.png) [@danmcb](https://www.ruby-forum.com/u/danmcb)\
**Post date:** [November 1, 2009, 9:52pm UTC](https://www.ruby-forum.com/t/enumerable-objectspace-222/177827/8 "2009-11-01T21:52:12Z")

</div>

I was impressed with these solutions. The use of an instance variable  
to store the argument I found particularly clever.

I had worked on something like this a long time ago. At the time I  
completely reimplemented Enumerable by hand to accept #each arguments  
(it was the first time I ever used TDD, btw). I later realized  
afterward a bit of meta-programming could make all of it a whole lot  
easier, so I created what is now enumargs.rb (gem install enumargs).  
It is similar to Benoit’s solution.

require ‘enumerator’

# This is a simple reimplementation of the core Enumerable module

# to allow the methods to take and pass-on arbitrary arguments to

the

# underlying #each call. This library uses Enumerator and scans

# Enumerable so it can alwasy stay in sync.

# 

# NOTE Any Enumerable method with a negative arity cannot pass

arguments

# due to ambiguity in the argument count. So the methods #inject and

#zip

# do NOT work this way, but simply work as they do in Enumerable.

# However the method #find, and it’s alias #detect, have been made

to work

# by removing its rarely used optional parameter and providing

instead an optional

# keyword parameter (:ifnone =\> …). Please keep these difference

in mind.

# 

# require ‘enumargs’

# 

# class T

# include Enumerable::Arguments

# def initialize(arr)

# @arr = arr

# end

# def each(n)

# arr.each{ |e| yield(e+n) }

# end

# end

# 

# t = T.new([1,2,3])

# t.collect(4)

# #=\> [5,6,7]

# 

module Enumerable  
module Arguments

```
def self.wrap_enumerable_method( methodname )

  m = methodname
  meth = Enumerable.instance_method(m)
  arity = meth.arity

  case arity <=> 0
  when 0
    class_eval %{
      def #{m}( *args, &yld )
        enum_for(:each, *args).#{m}( &yld )
      end
    }
  when 1
    class_eval %{
      def #{m}( *args, &yld )
        args, each_args = args[0...#{arity}], args[#{arity}..-1]
        enum_for(:each, *each_args).#{m}( *args, &yld )
      end
    }
  else
    class_eval %{
      def #{m}( *args, &yld )
        enum_for(:each).#{m}( *args, &yld )
      end
    }
  end
end

Enumerable.instance_methods(false).each do |m|
  wrap_enumerable_method( m )
end

# Make exception for #find (a negative arity method) to accept
# keyword argument.
#
# ObjectSpace.find(Class, :ifnone=>lambda{1}) { |e| ... }
# ObjectSpace.find(Class, :ifnone=>lambda{1}) { |e| ... }
#
def find(*args, &yld) # future use **keys ?
  if Hash === args.last and args.last.key?(:ifnone)
    ifnone = args.last.delete(:ifnone)
    args.pop if args.last.empty?
    enum_for(:each, *args).find( ifnone, &yld )
  else
    enum_for(:each, *args).find( &yld )
  end
end
alias_method :detect, :find

```

end  
end

With that, the solution to #222 is simply:

class \<\< ObjectSpace  
include Enumerable::Arguments  
alias each each\_object  
end

Eg.

ObjectSpace.select(Class){ |c| c \< Exception }

Thanks.

---

<div class="post-metadata">

**Author:** ![danmcb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/13edae/32.png) [@danmcb](https://www.ruby-forum.com/u/danmcb)\
**Post date:** [December 4, 2009, 8:01am UTC](https://www.ruby-forum.com/t/enumerable-objectspace-222/177827/9 "2009-12-04T08:01:42Z")

</div>

(Sorry for the delays!)

There were many great solutions to this week’s quiz.

James C. provides us with a compact solution using `method_missing`.

```
class << ObjectSpace
  def method_missing(sym, *args, &block)
    mod = args.first.is_a?(Module) ? args.shift : nil
    enum = enum_for(*[:each_object, mod].compact)
    enum. __send__ (sym, *args, &block)
  end
end

```

When calling an `Enumerable` method like `map` or `each` on  
`ObjectSpace` it will trigger `method_missing` as James’s solution  
does not have `ObjectSpace` include the `Enumerable` methods directly.  
The first argument, if present and a `Module` will be extracted. An  
enumerator is then created using `enum_for` and passing the given  
`Module`, if present, to the `each_object` method of `ObjectSpace`.  
The original method invoked that brought us into method missing in  
then invoked on the new enumerator with the remaining arguments and  
block. This will work for `map` as well as `inject` as long as the  
first argument is a `Module`. Methods such as `map` and `each` may be  
called with no `Module` given, in which case the block is called once  
for each living, nonimmediate object in the Ruby process. The density  
of meta-programming in James’s solution is a paragon of virtue and a  
good test of one’s meta-programming knowledge.

Benoit D.'s solution uses meta-programming to define new methods  
that accept a `Module` parameter for all the 0 arity methods in  
`Enumerable`. `each` is also redefined to accept a `Module` parameter,  
though this is not used by the redefined methods, they use `to_enum`  
and `select` to filter out all instances of the given `Module`.

```
objects = to_enum.select { |o| o.is_a? mod }

```

Robert K. added an `arg` method to `ObjectSpace` which stored the  
parameter in a thread local stack variable, so that calls may be  
nested. Robert’s `arg` method takes a block which is evaluated within  
the context of `ObjectSpace`. The `each` method is defined to call  
`each_object` with the parameter given by the top of the thread local  
stack variable.

Stefano C. and Intransition also gave some good solutions, view  
the attachment[1](http://rubyquiz.strd6.com/quizzes/222.tar.gz) for full details.

Thank you everyone for you solutions to this week’s quiz. It was fun  
and really mind stretching. Keep the suggestions coming!
