Hi~ On Aug 23, 2007, at 4:40 PM, Thomas Gantner wrote: > Hi > > I stumbled upon a problem with 'instance_eval' (using ruby 1.8.5 on > linux-x86_64). Simplified code example: > > irb:01> S = Struct.new(:a) > => S > irb:02> s = S.new(1) > => #<struct S a=1> > irb:03> s.a > => 1 > irb:04> s.a = 2 > => 2 > irb:05> s > => #<struct S a=2> > irb:06> s.instance_eval { puts a } > 2 > => nil > irb:07> s.instance_eval { a = 3 } > => 3 > irb:08> s > => #<struct S a=2> > irb:09> s.instance_eval { self.a = 3 } > => 3 > irb:10> s > => #<struct S a=3> > > My problem is in line 07: it seems that the 'a' in the block is > treated as a > local variable, therefore all the writer-accessor methods ('a=') > are hidden > within the block. I get the same result when instance_eval-ing the > string "a = 3" instead of the block variant. > > Is there a way to avoid this behaviour without using 'self.a' or > passing the > struct as a parameter into the block (which quite obsoletes the > meaning of > instance_eval)? > > My real world use of this pattern is using a block with 'initialize > ()': > > class C > def initialize(&blk) > @format = Struct.new( ... many, many elements with default > values ...) > @format.instance_eval(&blk) > end > end > > To explicitly override some default format-values I want to use > > c = C.new { elem8 = 8; elem17 = 'test'; ... } > > This won't work as explained above. I know I can use > > c = C.new {|format| format.elem8 = 8; format.elem17 = 'test'; ... } > > or > > c = C.new { self.elem8 = 8; self.elem17 = 'test'; ... } > > but both seem somewhat redundant and need too much typing (yeah I > know I'm > lazy ;-). > > Thanks for any suggestions. > > -Thomas > > -- > <sig. under construction> No unfortunately you are stuck with the behavior you observed. Whenever ruby sees 'a = b' it assumes it is a local variable assignment. This happens at parse time so there is no way to affect it at runtime. It's a tradeoff in order to allow local variables to look like method calls and visca versca. So you have to prefix an assignment with self. or another object, otherwise it is a local variable assignment and you cannot work around it since it happens at parse time. Cheers- -- Ezra Zygmuntowicz-- Founder & Ruby Hacker -- ez / engineyard.com -- Engine Yard, Serious Rails Hosting -- (866) 518-YARD (9273)