From: Jim Weirich Date: 2002-05-22T09:50:39+09:00 Subject: Re: Rewrite this without using eval... >>>>> "Jeff" == Jeff Gray writes: Jeff> I happened upon a situation where I wanted to apply a sequence of operations Jeff> to two instance variables without replicating the code. Here's the trivial Jeff> equivalent case, written using eval: Jeff> -- Jeff> class Foo Jeff> def initialize Jeff> @a = 1 Jeff> @b = 2 Jeff> end Jeff> def inc_iv Jeff> [:@a, :@b].each { |iv| Jeff> eval "#{iv} += 1" Jeff> } Jeff> end Jeff> end Jeff> -- Jeff> Could someone suggest a way to rewrite "inc_iv" without Jeff> using eval, without turning the guts of the each block into Jeff> a method, and without flattening the [:@a, :@b].each{} Jeff> construct? Interesting problem. Here's one solution, but you might find it a bit verbose.... class Ref def initialize(getter, setter) @getter, @setter = getter, setter end def value @getter.call end def value=(new_value) @setter.call(new_value) end end class Foo attr_reader :a, :b def initialize @a = 1 @b = 2 end def inc_iv [ Ref.new(proc {@a}, proc {|v| @a = v }), Ref.new(proc {@b}, proc {|v| @b = v }) ].each { |iv| iv.value += 1 } end end f = Foo.new f.inc_iv p f.a p f.b If you find the Ref.new(...) syntax a little verbose, you could write a function to generate it automatically, but that function would probably have to use eval ;-) -- -- Jim Weirich jweirich@one.net http://w3.one.net/~jweirich --------------------------------------------------------------------- "Beware of bugs in the above code; I have only proved it correct, not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)