From: "Jesús Gabriel y Galán" Date: 2009-12-24T20:19:09+09:00 Subject: Re: loses scope? On Thu, Dec 24, 2009 at 6:59 AM, Jeff Shantz wrote: > 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 >> => # >> 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 > => # >>> 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 > 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 => # 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 # from (irb):11:in `no_go' from (irb):14 from :0 Hope this helps, Jesus.