Getting an Error with local variable

C

Cheryl M.

class String
remove_method:)each)
end

class Object
def reach
if(x.respond_to?:)each))
self.each{|x| x.reach(yield)}
else
yield(self)
end
end
end


This is my code.. I keep getting the error that it can't find the local
variable 'x' .... why???
 
H

Haruka YAGNI

Hi, Cheryl
if(x.respond_to?:)each))
x is not defined here.
This is not x but self, isn't it?

The following code works well.

class String
remove_method:)each)
end

class Object
def reach
if(self.respond_to?:)each)) # <<<
self.each{|x| x.reach(yield)}
else
yield(self)
end
end
end

"hoge".reach { |myself|
print myself
}
 
S

Steve Klabnik

[Note: parts of this message were removed to make it a legal post.]

Because you use x here:

if(x.respond_to?:)each))


But it hasn't been defined.

You probably just want to remove that x.
 
H

Haruka YAGNI

multiple values for the block paramater(0 for 1)

You cannot set an argument for x.reach.
self.each{|x| x.reach(yield)}

Instead,
self.each{|x| x.reach{|y| yield y}}
This works but is not elegant.
Somebody has an idea?
 
R

Robert Klemme

You cannot set an argument for x.reach.
=A0self.each{|x| x.reach(yield)}

Instead,
=A0self.each{|x| x.reach{|y| yield y}}
This works but is not elegant.
Somebody has an idea?

The approach is broken because the block is not carried through the
recursion. Please see my recent reply in thread "Creating a Reach
Program" a few days back. Cheryl, did you actually read it?

robert

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

Haruka YAGNI

Robert, thank you for the reply.

The approach is broken because the block is not carried through the
recursion.

I read your previous post. I like it.
It is elegant to useblock instead of yield and to add reach method to
Enumerable module.

I am curious about when my code does not work.
I tested the next script and it printed the same as your code.

class String
remove_method:)each)
end

class Object
def reach
if(self.respond_to?:)each))
self.each{|x| x.reach{|y| yield y}}
else
yield(self)
end
end
end

[["hoge", "huga"],["foo", "bar"]].reach { |myself|
print myself
}

With a nested array, a new block is given to the next 'reach'.
So, I think, if I write this without recursion (of course impossible),
the whole prosess is like
some_array.each{|x1| x1.each{|x2| x2.each{ .... xn.each {|myself|
print myself} ....}}}
and xn is an unnested array.

If I misunderstand something, or my program has a bug, please let me know.

Thanks.

Haruka YAGNI
 
R

Robert Klemme

Robert, thank you for the reply.



I read your previous post. =A0I like it.
It is elegant to useblock instead of yield and to add reach method to
Enumerable module.

I am curious about when my code does not work.
I tested the next script and it printed the same as your code.

class String
=A0remove_method:)each)
end

This is only needed in 1.8.* btw.

$ allruby -e 'String.instance_method "each"'
CYGWIN_NT-5.1 padrklemme2 1.7.9(0.237/5/3) 2011-03-29 10:10 i686 Cygwin
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
ruby 1.8.7 (2008-08-11 patchlevel 72) [i386-cygwin]
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
ruby 1.9.2p180 (2011-02-18 revision 30909) [i386-cygwin]
-e:1:in `instance_method': undefined method `each' for class `String'
(NameError)
from -e:1:in `<main>'
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
jruby 1.6.0 (ruby 1.8.7 patchlevel 330) (2011-03-15 f3b6154) (Java
HotSpot(TM) Client VM 1.6.0_24) [Windows XP-x86-java]
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
jruby 1.6.0 (ruby 1.9.2 patchlevel 136) (2011-03-15 f3b6154) (Java
HotSpot(TM) Client VM 1.6.0_24) [Windows XP-x86-java]
NameError: undefined method `each' for class `String'
instance_method at org/jruby/RubyModule.java:1957
(root) at -e:1
class Object
=A0def reach
=A0 if(self.respond_to?:)each))
=A0 =A0 self.each{|x| x.reach{|y| yield y}}
=A0 else
=A0 =A0 yield(self)
=A0 end
=A0end
end

[["hoge", "huga"],["foo", "bar"]].reach { |myself|
=A0print myself
}

With a nested array, a new block is given to the next 'reach'.
So, I think, if I write this without recursion (of course impossible),
the whole prosess is like
=A0 some_array.each{|x1| x1.each{|x2| x2.each{ .... xn.each {|myself|
print myself} ....}}}
and xn is an unnested array.

If I misunderstand something, or my program has a bug, please let me know=
 
H

Haruka YAGNI

I'm afraid the bug is in my brain. =A0You are right. =A0I am sorry. =A0I
should have taken more time to look at this.

No problem at all.
That approach does produce awful call stacks though (with multiple
levels of nesting the call chain has to go backwards up to the topmost
caller to invoke the block initially provided to reach; you can see
this by adding "puts caller" to the beginning of the block). I find it
more elegant to pass the block down and have it invoked immediately.
Apparently you agree with me here.

Yes, I agree at all points.
When I do something like this in my application, I will use your
solution with appreciation.

Thank you for you kind information.


regards

Haruka YAGNI
 

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

Forum statistics

Threads
473,982
Messages
2,570,190
Members
46,740
Latest member
AdolphBig6

Latest Threads

Top