# Method lookup from a Lambda

**URL:** <https://www.ruby-forum.com/t/method-lookup-from-a-lambda/136448>\
**Category:** Ruby\
**Created:** [May 2, 2008, 7:35am UTC](https://www.ruby-forum.com/t/method-lookup-from-a-lambda/136448 "2008-05-02T07:35:24Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![amin1426](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/4da419/32.png) [@amin1426](https://www.ruby-forum.com/u/amin1426)\
**Post date:** [May 2, 2008, 7:35am UTC](https://www.ruby-forum.com/t/method-lookup-from-a-lambda/136448/1 "2008-05-02T07:35:24Z")

</div>

Hi all,

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:

module Fix  
def self.manage()  
lambda do  
what = foo? ? “fix” : “leave”  
“Let’s " + what + " 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

# Let’s fix it

# Let’s leave it

This does not:

module Fix  
def self.doer()  
lambda do  
foo? ? “fix” : “leave”  
end  
end

```
def self.manage()
  grunt = doer
  lambda do
    "Let's " + grunt.call + " 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

# lambda2.rb:4:in `doer': undefined method`foo?’ for Fix:Module

(NoMethodError)

# from lambda2.rb:10:in `call’

# from lambda2.rb:10:in `maintenance’

# from lambda2.rb:25

In the first example, the call to the method the mixin module relies on  
gets called without problem. I. e. the instance method of the mixin  
finds the object’s instance method. However, in the second example,  
methods are not looked up the same way, the module is searched and so it  
fails.

What about the second example’s closure on the lambda is causing  
method’s to be looked up differently? I do not feel like I have a good  
mental model of the method lookup and scoping rules of Ruby. The latest  
book I’ve looked at (Programming Ruby) doesn’t seem to shed much light  
on my issue.

Can anyone give me an explanation to help?

Thank you,  
John

---

<div class="post-metadata">

**Author:** ![amin1426](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/4da419/32.png) [@amin1426](https://www.ruby-forum.com/u/amin1426)\
**Post date:** [May 3, 2008, 2:04am UTC](https://www.ruby-forum.com/t/method-lookup-from-a-lambda/136448/2 "2008-05-03T02:04:02Z")

</div>

On Fri, May 2, 2008 at 6:35 AM, John C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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.

> ```
> lambda do
> 
> ```

# use instance\_eval(&block) instead of block.call

```
     "Let's " + instance_eval(&grunt) + " it"

```

> 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

---

<div class="post-metadata">

**Author:** ![amin1426](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/4da419/32.png) [@amin1426](https://www.ruby-forum.com/u/amin1426)\
**Post date:** [May 10, 2008, 12:01am UTC](https://www.ruby-forum.com/t/method-lookup-from-a-lambda/136448/3 "2008-05-10T00:01:46Z")

</div>

Sean O’halpin wrote:

> It does with the fix below.
> 
> > ```
> > lambda do
> > 
> > ```
> 
> # use instance\_eval(&block) instead of block.call
> 
> ```
> "Let's " + instance_eval(&grunt) + " it"
> 
> ```

Is there a way to pass arguments to &grunt during the invocation? The  
call method allows arguments to be passed to the lambda’s that expect  
them. While my example does not show such a lambda, this is a feature I  
currently require. If grunt did require arguments, how could I pass  
them?

TIA,  
John

---

<div class="post-metadata">

**Author:** ![amin1426](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/4da419/32.png) [@amin1426](https://www.ruby-forum.com/u/amin1426)\
**Post date:** [May 10, 2008, 3:05am UTC](https://www.ruby-forum.com/t/method-lookup-from-a-lambda/136448/4 "2008-05-10T03:05:20Z")

</div>

On Fri, May 9, 2008 at 11:01 PM, John C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > ```
> > "Let's " + instance_eval(&grunt) + " it"
> > 
> > ```
> 
> Is there a way to pass arguments to &grunt during the invocation? The  
> call method allows arguments to be passed to the lambda’s that expect  
> them. While my example does not show such a lambda, this is a feature I  
> currently require. If grunt did require arguments, how could I pass  
> them?

Hi,

You need instance\_exec, which is native in 1.9 but has to be  
implemented in Ruby in 1.8.  
The version below is the best one I have to hand. (There may be a  
better one on Mauricio’s blog but [eigenclass.org](http://eigenclass.org) is coming up with a  
hiki error at the moment so I can’t check).

Regards,  
Sean

# 

# instance\_exec for ruby 1.8 by Mauricio F.

# [eigenclass.org](http://eigenclass.org/hiki.rb?bounded+space+instance_exec)

# thread-safe and handles frozen objects in bounded space

# 

class Object  
module InstanceExecHelper; end  
include InstanceExecHelper  
def instance\_exec(\*args, &block)  
begin  
old\_critical, Thread.critical = Thread.critical, true  
n = 0  
methods = InstanceExecHelper.instance\_methods  
# this in order to make the lookup O(1), and name generation O(n)  
on the  
# number of nested/concurrent instance\_exec calls instead of  
O(n\*\*2)  
table = Hash[\*methods.zip(methods).flatten]  
n += 1 while table.has\_key?(mname=“\_\_instance\_exec#{n}”)  
ensure  
Thread.critical = old\_critical  
end  
InstanceExecHelper.module\_eval{ define\_method(mname, &block) }  
begin  
ret = send(mname, \*args)  
ensure  
InstanceExecHelper.module\_eval{ remove\_method(mname) } rescue nil  
end  
ret  
end  
end
