Creating a Reach Program

The reach method is like the standard each method, except that it
applies to the leaves of container objects.
It takes : [4, [13, 88], [19, “fred”, “snark”], “alice”].each { |x|
print x, “\n”}
and makes it look like:
4
13
88
19
fred
snark
alice

i have this so far::

class String
remove_method(:each)
end

class Object
def reach
#checking if responds to each and if so prints it out else
# returns the objects yielded
if(x.respond_to?(:each))
self.each{|x|}
else
yield(self)

end
end

I am not sure what to do in the if part of this problem…
The body of reach checks whether the self has the each method. If not,
simply yield(self); otherwise run the each method on yourself and call
reach on each component, sending it a code block that simply calls yield
on its argument. To find out if an object x has a particular method m,
you may use x.respond_to?(m), where m is a string giving the name.

On Sun, Mar 27, 2011 at 10:42 PM, Cheryl M. [email protected]
wrote:

snark
alice

i have this so far::

class String
remove_method(:each)
end

Obviously you are on 1.8.*. Even then I’d consider it a bad idea to
remove this method from a standard class because it may break other
code.

end

I am not sure what to do in the if part of this problem…

First of all you should make sure x is actually defined.

The body of reach checks whether the self has the each method. If not,
simply yield(self); otherwise run the each method on yourself and call
reach on each component, sending it a code block that simply calls yield
on its argument.

Actually your code only invokes #each on self and doesn’t do anything
further, especially not pass it to the block associated with this
method call.

To find out if an object x has a particular method m,
you may use x.respond_to?(m), where m is a string giving the name.

First thing you should do is to pass the block around, because you
have a recursive invocation here. For that you need the &b syntax:

class Object
EACH = lambda {|o| o.respond_to? :each}
class <<EACH
alias :=== :[]
end

def reach(&b)
case self
when String
b[self]
when Hash
# we follow only values!
each {|k,v| v.reach(&b)}
when Enumerable, EACH
each {|x| x.reach(&b)}
else
b[self]
end
self
end
end

A more OO approach would use the own type for definitions:

[Object, String].each do |cl|
cl.class_eval do
def reach
yield self
self
end
end
end

module Enumerable
def reach(&b)
each {|x| x.reach(&b)}
end
end

class Hash
def reach(&b)
# we follow only values!
each {|k,v| v.reach(&b)}
end
end

Note, in 1.9 you do not need special treatment for class String as it
does not mix in Enumerable.

Kind regards

robert

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs