From: Joel VanderWerf Date: 2006-10-26T06:38:41+09:00 Subject: Re: Pass block instead of here document? James Edward Gray II wrote: > On Oct 25, 2006, at 2:54 PM, dblack@wobblini.net wrote: > >> It's easy, but it can also be a bit obfuscating. For example: >> >> class C >> def initialize(thing) >> @thing = thing >> end >> >> def tell(&block) >> instance_eval(&block) >> end >> end >> >> c = C.new("Hi") >> >> @thing = "Hello" >> c.tell do >> puts @thing # Hi >> end >> >> So you get some perhaps unwanted variable-shadowing, and similarly >> with method calls. > > Greg Brown and I were playing around with a solution for the method call > issue at RubyConf. Here's the code we came up with: > > class C > def initialize(thing) > @thing = thing > end > > attr_reader :thing > > def tell(&block) > if block and block.arity == 1 > block[self] > else > instance_eval(&block) > end > end > end > > def thing; "Hello" end > > c = C.new("Hi") > > c.tell do > thing # => "Hi" > end > > c.tell do |obj| > thing # => "Hello" > obj.thing # => "Hi" > end > > I know people frown on the instance_eval() trick, but this seems to be > less of a problem. You can just choose to use the variable when you > need it. I dunno... the presence of "|obj|" changes the semantics of the rest of the block. It's so easy to comment out the |obj| and then suddenly methods are handled in a surprising way: c.tell do |obj| thing # => "Hello" end c.tell do #|obj| thing # => "Hi" end Visually, it doesn't look like anything important has changed. Seems like a bug magnet. -- vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407