# Dynamically defining a method on an instance that references vars in enclosing scope?

**URL:** <https://www.ruby-forum.com/t/dynamically-defining-a-method-on-an-instance-that-references-vars-in-enclosing-scope/132581>\
**Category:** Ruby\
**Created:** [March 21, 2008, 5:15pm UTC](https://www.ruby-forum.com/t/dynamically-defining-a-method-on-an-instance-that-references-vars-in-enclosing-scope/132581 "2008-03-21T17:15:11Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Christopher\_JSBott](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/ee7513/32.png) [@Christopher\_JSBott](https://www.ruby-forum.com/u/Christopher_JSBott)\
**Post date:** [March 21, 2008, 5:15pm UTC](https://www.ruby-forum.com/t/dynamically-defining-a-method-on-an-instance-that-references-vars-in-enclosing-scope/132581/1 "2008-03-21T17:15:11Z")

</div>

Hello. I want to do this.

instance = MyClass.new  
x = 1  
def instance.foo  
puts x  
end  
undefined local variable or method `x’ for #MyClass:0x31ca8c4

How do get rid of that error?

Thanks for the help.

---

<div class="post-metadata">

**Author:** ![Christopher\_JSBott](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/ee7513/32.png) [@Christopher\_JSBott](https://www.ruby-forum.com/u/Christopher_JSBott)\
**Post date:** [March 21, 2008, 5:33pm UTC](https://www.ruby-forum.com/t/dynamically-defining-a-method-on-an-instance-that-references-vars-in-enclosing-scope/132581/2 "2008-03-21T17:33:00Z")

</div>

Hi –

On Sat, 22 Mar 2008, Christopher J. Bottaro wrote:

> Hello. I want to do this.
> 
> instance = MyClass.new  
> x = 1  
> def instance.foo  
> puts x  
> end  
> undefined local variable or method `x’ for #MyClass:0x31ca8c4
> 
> How do get rid of that error?

You can use define\_method, which takes a block and therefore can use  
the local variables in scope at the time it’s called. You’d have to do  
something equivalent to the familiar:

class Object  
def singleton\_class  
class \<\< self  
self  
end  
end  
end

(Aside to Matz: can we _please_ have that in 1.9/2.0? 🙂

and then:

instance.singleton\_class.class\_eval {  
define\_method(“foo”) { puts x }  
}

David

---

<div class="post-metadata">

**Author:** ![Christopher\_JSBott](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/ee7513/32.png) [@Christopher\_JSBott](https://www.ruby-forum.com/u/Christopher_JSBott)\
**Post date:** [March 21, 2008, 5:55pm UTC](https://www.ruby-forum.com/t/dynamically-defining-a-method-on-an-instance-that-references-vars-in-enclosing-scope/132581/3 "2008-03-21T17:55:39Z")

</div>

The problem is of scope. foo is a method belonging to the ‘instance’  
variable. ‘x’ is defined in global scope, but since its not $x its not  
a global variable. When you start using x inside the method, the  
interpreter doesn’t recognize a ‘x’ variable defined, hence the error.  
Either, define x inside MyClass, or mark x as a global variable using  
$x, which would make…

…  
$x = 1  
def instance.foo  
puts $x  
end

to: Christopher  
I’d start off with a good introduction to scopes, that’ll clear this  
scenario out. Plus buy the pickaxe book. Great read for beginners.

---

<div class="post-metadata">

**Author:** ![Christopher\_JSBott](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/ee7513/32.png) [@Christopher\_JSBott](https://www.ruby-forum.com/u/Christopher_JSBott)\
**Post date:** [March 21, 2008, 6:06pm UTC](https://www.ruby-forum.com/t/dynamically-defining-a-method-on-an-instance-that-references-vars-in-enclosing-scope/132581/4 "2008-03-21T18:06:50Z")

</div>

Hi –

On Sat, 22 Mar 2008, mutahhir hayat wrote:

> > > def instance.foo  
> > > class Object
> 
> $x, which would make…
> 
> …  
> $x = 1  
> def instance.foo  
> puts $x  
> end

I know that the problem is scope. That’s why I suggested a way to  
manipulate the scope 🙂

I definitely would not (and deliberately did not) throw a global  
variable at it. Also, defining x inside MyClass doesn’t help, because  
that’s also a different local scope.

David

---

<div class="post-metadata">

**Author:** ![Christopher\_JSBott](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/ee7513/32.png) [@Christopher\_JSBott](https://www.ruby-forum.com/u/Christopher_JSBott)\
**Post date:** [March 21, 2008, 6:29pm UTC](https://www.ruby-forum.com/t/dynamically-defining-a-method-on-an-instance-that-references-vars-in-enclosing-scope/132581/5 "2008-03-21T18:29:23Z")

</div>

> I know that the problem is scope. That’s why I suggested a way to  
> manipulate the scope 🙂
> 
> I definitely would not (and deliberately did not) throw a global  
> variable at it. Also, defining x inside MyClass doesn’t help, because  
> that’s also a different local scope.

I wasn’t sure, but running an intermix of your code with the original  
still would give the same error in irb. I wasn’t advocating the use of  
globals, ( though, come to think about it, i do feel bad now even  
mentioning it :P) but I didn’t consider that x wouldn’t be usable.

🙂 I’m still getting used to this metaprogramming thing, but how did  
you change scope? In my view, the scope remains exactly same, you just  
allowed the method to be inserted into the object instance  
dynamically.

Anyways, simplest i found was: (swearing never to mention global  
again… :P)

class MyClass  
attr\_accessor :x  
#… or if you want you could do

# def initialize(x); @x = x; end

end

instance = MyClass.new

def instance.foo  
puts x  
end

instance.x = 1  
instance.foo

would work.

MT.

---

<div class="post-metadata">

**Author:** ![Christopher\_JSBott](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/ee7513/32.png) [@Christopher\_JSBott](https://www.ruby-forum.com/u/Christopher_JSBott)\
**Post date:** [March 21, 2008, 6:56pm UTC](https://www.ruby-forum.com/t/dynamically-defining-a-method-on-an-instance-that-references-vars-in-enclosing-scope/132581/6 "2008-03-21T18:56:07Z")

</div>

On Sat, Mar 22, 2008 at 1:37 AM, David A. Black [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> > > that’s also a different local scope.
> > 
> > I wasn’t sure, but running an intermix of your code with the original  
> > still would give the same error in irb. I wasn’t advocating the use of  
> > globals, ( though, come to think about it, i do feel bad now even  
> > mentioning it :P) but I didn’t consider that x wouldn’t be usable.
> 
> I don’t see the error:

Sorry, my bad, i rewrote it in my irb, and it validates your code. 🙂  
Must be getting to bed now, clock’s slowing.

> irb(main):009:0\* instance = Object.new
> 
> the locals that are already in scope.)

I get you, since the block passed to class\_eval was defined in the  
same scope as x, it would be knowledgeable about it. But tell me,  
other than academic, won’t this be really bad to use? Like, maybe you  
shadow some variable, and so on… I dunno, 😛 as i said, nearing my  
limit, so maybe i’m just jabbering here. But it was fun learning from  
you, glad to be on this list. Thanks.

( Although, according to my judgment (sorry if i’m wrong) of the level  
of the programmer by the nature of the question, i’m pretty sure we  
made the questioner scream ) 🙂

See ya,  
MT

---

<div class="post-metadata">

**Author:** ![Christopher\_JSBott](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/ee7513/32.png) [@Christopher\_JSBott](https://www.ruby-forum.com/u/Christopher_JSBott)\
**Post date:** [March 21, 2008, 6:38pm UTC](https://www.ruby-forum.com/t/dynamically-defining-a-method-on-an-instance-that-references-vars-in-enclosing-scope/132581/7 "2008-03-21T18:38:17Z")

</div>

Hi –

On Sat, 22 Mar 2008, mutahhir hayat wrote:

> mentioning it :P) but I didn’t consider that x wouldn’t be usable.  
> I don’t see the error:

irb(main):001:0\> class Object  
irb(main):002:1\> def singleton\_class  
irb(main):003:2\> class \<\< self  
irb(main):004:3\> self  
irb(main):005:3\> end  
irb(main):006:2\> end  
irb(main):007:1\> end  
=\> nil  
irb(main):008:0\>  
irb(main):009:0\* instance = Object.new  
=\> #Object:0x64f50  
irb(main):010:0\> x = 1  
=\> 1  
irb(main):011:0\>  
irb(main):012:0\* instance.singleton\_class.class\_eval {  
irb(main):013:1\* define\_method(“foo”) { puts x }  
irb(main):014:1\> }  
=\> #Proc:0x00058728@:13(irb)  
irb(main):015:0\>  
irb(main):016:0\* instance.foo  
1

> 🙂 I’m still getting used to this metaprogramming thing, but how did  
> you change scope? In my view, the scope remains exactly same, you just  
> allowed the method to be inserted into the object instance  
> dynamically.

That’s the thing: I didn’t change scope. The block that uses x (line  
013 above) is in the same scope as the line that defines x (010) – at  
least, in the same scope block-style. (Meaning: the block can see all  
the locals that are already in scope.)

> def instance.foo  
> puts x  
> end
> 
> instance.x = 1  
> instance.foo
> 
> would work.

Yes, but you’ve shifted to instance variables. That’s a more common  
use case than the class\_eval/define\_method one, but they’re both worth  
knowing about.

David

---

<div class="post-metadata">

**Author:** ![Christopher\_JSBott](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/ee7513/32.png) [@Christopher\_JSBott](https://www.ruby-forum.com/u/Christopher_JSBott)\
**Post date:** [March 21, 2008, 7:26pm UTC](https://www.ruby-forum.com/t/dynamically-defining-a-method-on-an-instance-that-references-vars-in-enclosing-scope/132581/8 "2008-03-21T19:26:53Z")

</div>

Hi –

On Sat, 22 Mar 2008, mutahhir hayat wrote:

> I get you, since the block passed to class\_eval was defined in the  
> same scope as x, it would be knowledgeable about it. But tell me,  
> other than academic, won’t this be really bad to use? Like, maybe you  
> shadow some variable, and so on… I dunno, 😛 as i said, nearing my  
> limit, so maybe i’m just jabbering here. But it was fun learning from  
> you, glad to be on this list. Thanks.

One of the most important roles of code blocks is to serve as closures  
– that is, functions that remember the context of their own creation.  
In Ruby 1.9, the rules of parameter assignment are changing somewhat,  
so that it’s easier to avoid trampling outside variables; but you can  
still use those variables if that’s your purpose.

David

---

<div class="post-metadata">

**Author:** ![Christopher\_JSBott](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/ee7513/32.png) [@Christopher\_JSBott](https://www.ruby-forum.com/u/Christopher_JSBott)\
**Post date:** [April 2, 2008, 10:22pm UTC](https://www.ruby-forum.com/t/dynamically-defining-a-method-on-an-instance-that-references-vars-in-enclosing-scope/132581/9 "2008-04-02T22:22:51Z")

</div>

On Mar 21, 1:26 pm, “David A. Black” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> One of the most important roles of code blocks is to serve as closures  
> That is what I was going for. Thank you for your solution!

> You’d have to do something equivalent to the familiar:  
> class Object  
> def singleton\_class  
> class \<\< self  
> self  
> end  
> end  
> end

Though I more or less understand what that is doing, it’s not  
“familiar” to me. Can you tell me name of that idiom or point me in  
the direction of where it is discussed?

I do understand that if I simply do something like

my\_instance.class.define\_method :name do

# blah blah

end

Then ‘name’ will be defined for all instances of the class and not  
just for the few instances that I want.

Thanks again.

\<off\_topic\_rant\>  
I wish Google G. would send email notification to threads I  
participate in by default. So many times I forget that I even posted  
until months later.  
\</off\_topic\_rant\>
