From: Robert Klemme Date: 2008-08-09T17:28:09+09:00 Subject: Re: Works in irb but not elsewhere On 08.08.2008 23:01, cardboard42@gmail.com wrote: > I think what's happening is that yield is calling the block passed to > the caller of instance_eval so method is being called on self in that > block's closure. Since it was executed at the top level that would be > Object. Object.method takes 1 parameter, thus causing the error you're > seeing. The reason the code I posted works because it takes the block > passed to create and passes it directly to instance_eval as it's > block. This means that method will be called on self in instance_eval, > where it is set to the object instance_eval is called on, in this case > the result of A.new. > > Sorry if my explanation is hard to understand, but I'm positive this > is not a bug in ruby. instance_eval { yield } simply has very > different semantics from instance_eval &block. Absolutely correct, there is no bug - at least not in Ruby. You can also see it from this: $ ruby < class A > def method > puts "a" > end > def A.create > A.new.instance_eval { yield } > end > end > > A.create{ p self; method} > > XXX main -:10:in `method': wrong number of arguments (0 for 1) (ArgumentError) from -:10 from -:6:in `create' from -:6:in `instance_eval' from -:6:in `create' from -:10 Note the output of "p self": it's main. And this is the case because self is not changed for the block invoked via "yield". Note also that this does not work in IRB as well: $ irb irb(main):001:0> class A irb(main):002:1> def method irb(main):003:2> puts "a" irb(main):004:2> end irb(main):005:1> def A.create irb(main):006:2> A.new.instance_eval { yield } irb(main):007:2> end irb(main):008:1> end => nil irb(main):009:0> irb(main):010:0* A.create{ p self; method} main ArgumentError: wrong number of arguments (0 for 1) from (irb):10:in `method' from (irb):10 from (irb):6:in `create' from (irb):6:in `instance_eval' from (irb):6:in `create' from (irb):10 irb(main):011:0> Kind regards robert