Loses scope?

Anybody know why this fails?

a = 32
class A
def go
a
end
end
puts A.new.go # raises with “a not defined”

?
Thanks.
-r

On Fri, Dec 18, 2009 at 11:06 PM, Roger P. [email protected]
wrote:

?
Because both “class” and “def” keywords create a new scope. They are
not closures, they don’t see their surrounding scope. Consider this
other way, which doesn’t create new scopes:

irb(main):001:0> a = 3
=> 3
irb(main):008:0> Test = Class.new do
irb(main):009:1* define_method(:go) do
irb(main):010:2* puts a
irb(main):011:2> end
irb(main):012:1> end
=> Test
irb(main):013:0> Test.new.go
3
=> nil

Jesus.

Jesús Gabriel y Galán wrote:

Because both “class” and “def” keywords create a new scope. They are
not closures, they don’t see their surrounding scope. Consider this
other way, which doesn’t create new scopes:

That I did not know. Thanks!
-r

On 12/18/2009 2:06 PM, Roger P. wrote:

Anybody know why this fails?

a = 32
class A
def go
a
end
end
puts A.new.go # raises with “a not defined”

You may want to call class_eval and define_method with blocks instead.

On Dec 18, 3:27 pm, Roger P. [email protected] wrote:

Jesús Gabriel y Galán wrote:

Because both “class” and “def” keywords create a new scope. They are
not closures, they don’t see their surrounding scope. Consider this
other way, which doesn’t create new scopes:

Ah thanks for posting that, I’m rather new to ruby and that was
confusing me.

puts A.new.go # raises with “a not defined”

You may want to call class_eval and define_method with blocks instead.

Hmm. Perhaps an example using class_eval would help me understand that
better (define_method works great, BTW).
Thanks!
-r

Jesús Gabriel y Galán wrote:

irb(main):006:0> A.class_eval do
irb(main):007:1* define_method(:go) do

Many thanks and merry Christmas.
-r

On Sun, Dec 20, 2009 at 3:56 AM, Roger P. [email protected]
wrote:

puts A.new.go # raises with “a not defined”

You may want to call class_eval and define_method with blocks instead.

Hmm. Perhaps an example using class_eval would help me understand that
better (define_method works great, BTW).
Thanks!

irb(main):001:0> class A
irb(main):002:1> end
=> nil
irb(main):005:0> a = 3
=> 3
irb(main):006:0> A.class_eval do
irb(main):007:1* define_method(:go) do
irb(main):008:2* puts a
irb(main):009:2> end
irb(main):010:1> end
=> #Proc:[email protected]:7(irb)
irb(main):011:0> A.new.go
3
=> nil

When you already have the class A created and you open it to add the
‘go’ method, you can use class_eval, which receives a block. Blocks
are closures, so they see their surrounding scope, and thus, the
variable ‘a’.

Jesus.

On Thu, Dec 24, 2009 at 6:59 AM, Jeff S. [email protected]
wrote:

irb(main):010:1> end
=> A
=> B

B.class_eval do
?> def test

  puts "Testing!!"
end

end
=> nil

B.new.test
Testing!!
=> nil

The difference is that def starts a new scope, it’s not a closure, so
it doesn’t see its surrounding scope. In the following case (as well
as the original case by the OP), the local variable ‘a’ is seen in the
block passed to define_method, but not to the body of the ‘def’
keyword, since it’s not a closure:

irb(main):001:0> class A; end
=> nil
irb(main):002:0> a = 3
=> 3
irb(main):003:0> A.class_eval do
irb(main):004:1* define_method(:go) do
irb(main):005:2* puts a # this a is the a outside the
class_eval
irb(main):006:2> end
irb(main):007:1> end
=> #Proc:[email protected]:4(irb)
irb(main):008:0> A.new.go
3
=> nil
irb(main):009:0> A.class_eval do
irb(main):010:1* def no_go
irb(main):011:2> puts a #this one is undefined
irb(main):012:2> end
irb(main):013:1> end
=> nil
irb(main):014:0> A.new.no_go
NameError: undefined local variable or method a' for #<A:0xb7870584> from (irb):11:inno_go’
from (irb):14
from :0

Hope this helps,

Jesus.

Jesús Gabriel y Galán wrote:

irb(main):001:0> class A
irb(main):002:1> end
=> nil
irb(main):005:0> a = 3
=> 3
irb(main):006:0> A.class_eval do
irb(main):007:1* define_method(:go) do
irb(main):008:2* puts a
irb(main):009:2> end
irb(main):010:1> end
=> #Proc:[email protected]:7(irb)
irb(main):011:0> A.new.go
3
=> nil

Just curious… is there any difference between using define_method and
def in this case? It seems they achieve the same effect. Why would one
be preferred over the other?

A = Class.new
=> A

A.class_eval do
?> define_method(:test) do
?> puts “Testing!”

end

end
=> #Proc:[email protected]:3(irb)

A.new.test
Testing!
=> nil

B = Class.new
=> B

B.class_eval do
?> def test

  puts "Testing!!"
end

end
=> nil

B.new.test
Testing!!
=> nil

Thanks.

Jeff