From: Sean O'Halpin Date: 2008-05-03T09:03:20+09:00 Subject: Re: Method lookup from a Lambda On Fri, May 2, 2008 at 6:35 AM, John Conti wrote: > Hi all, Hi > > I am not sure if my question is relatively obvious or instead arcane. > Being new to ruby, I am trying out some of the metaprogramming features > to generate sets of orthogonal methods for decoding various string > types. I want to provide these methods as mix-ins so many of my classes > can decode these specialized strings. The methods have lots of > repetitive code and are easily reduced using lambdas (think DRY). > > However, all has not gone as I expected. This works: [snip code] > > This does not: It does with the fix below. > > module Fix > def self.doer() > lambda do > foo? ? "fix" : "leave" > end > end > > def self.manage() > grunt = doer > lambda do # use instance_eval(&block) instead of block.call "Let's " + instance_eval(&grunt) + " it" > end > end > > module_eval %{define_method :maintenance, manage} > end > > class X > include Fix > def foo?; true; end > end > > class Y > include Fix > def foo?; false; end > end > > puts X.new.maintenance > puts Y.new.maintenance > Output: Let's fix it Let's leave it > > Can anyone give me an explanation to help? > When you use block.call, the block is evaluated in the context in which it was defined. In the case of the block defined in #doer this is the singleton class of the module Fix, which does not have a #foo? method. Using instance_eval tells Ruby to evaluate the block in the context of an object instance. Without a specific receiver, this is the current #self - in this case, the object of the class in which you have included the module Fix. This does have a #foo? method, so the block executes. HTH Regards, Sean