Creating a Reach Program

C

Cheryl M.

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.
 
R

Robert Klemme

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
=A0remove_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.
class Object
=A0def reach
=A0 =A0#checking if responds to each and if so prints it out else
=A0 =A0# returns the objects yielded
if(x.respond_to?:)each))
=A0 =A0self.each{|x|}
=A0else
=A0 =A0yield(self)

=A0end
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 =3D lambda {|o| o.respond_to? :each}
class <<EACH
alias :=3D=3D=3D :[]
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

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top