# Dynamic local vars

**URL:** <https://rubytalk.org/t/dynamic-local-vars/42823>\
**Category:** ruby-talk\
**Created:** [7 December 2007 08:19 UTC](https://rubytalk.org/t/dynamic-local-vars/42823 "2007-12-07T08:19:55Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![Vasyl\_Smirnov](https://avatars.discourse-cdn.com/v4/letter/v/ecc23a/32.png) [@Vasyl\_Smirnov](https://rubytalk.org/u/Vasyl_Smirnov)\
**Post date:** [7 December 2007 08:19 UTC](https://rubytalk.org/t/dynamic-local-vars/42823/1 "2007-12-07T08:19:55Z")

</div>

Hi,

I wonder if there is any way to create local variables dynamically,  
for example, given

def foo  
&nbsp;&nbsp;bar  
&nbsp;&nbsp;puts x, y  
end

is it possible for bar to somehow create and initialize x and y?  
Binding doesn't seem to be modifiable..

Or am I asking too much? 🙂

---

<div class="post-metadata">

**Author:** ![Jordan\_Callicoat](https://avatars.discourse-cdn.com/v4/letter/j/9de053/32.png) [@Jordan\_Callicoat](https://rubytalk.org/u/Jordan_Callicoat)\
**Post date:** [7 December 2007 09:35 UTC](https://rubytalk.org/t/dynamic-local-vars/42823/2 "2007-12-07T09:35:12Z")

</div>

There are probably more clever ways than this, but I'm dumb...

def bar  
&nbsp;&nbsp;x = 10  
&nbsp;&nbsp;y = 20  
&nbsp;&nbsp;binding  
end

def foo  
&nbsp;&nbsp;eval("puts x, y", bar)  
end

Regards,  
Jordan

> **···**
>
> On Dec 7, 2:19 am, Vasyl Smirnov \<vasyl.smir...@gmail.com\> wrote:
> 
> > Hi,
> > 
> > I wonder if there is any way to create local variables dynamically,  
> > for example, given
> > 
> > def foo  
> > &nbsp;&nbsp;bar  
> > &nbsp;&nbsp;puts x, y  
> > end
> > 
> > is it possible for bar to somehow create and initialize x and y?  
> > Binding doesn't seem to be modifiable..
> > 
> > Or am I asking too much? 🙂

---

<div class="post-metadata">

**Author:** ![Tim\_Hunter4](https://avatars.discourse-cdn.com/v4/letter/t/ea5d25/32.png) [@Tim\_Hunter4](https://rubytalk.org/u/Tim_Hunter4)\
**Post date:** [7 December 2007 13:06 UTC](https://rubytalk.org/t/dynamic-local-vars/42823/3 "2007-12-07T13:06:15Z")

</div>

Vasyl Smirnov wrote:

> Hi,
> 
> I wonder if there is any way to create local variables dynamically,  
> for example, given
> 
> def foo  
> &nbsp;&nbsp;bar  
> &nbsp;&nbsp;puts x, y  
> end
> 
> is it possible for bar to somehow create and initialize x and y?  
> Binding doesn't seem to be modifiable..
> 
> Or am I asking too much? 🙂

Hmmm...local variables are called local because they're local to the method that uses them. A variable that's shared between two methods isn't local.

If foo and bar are both methods in the same class, use instance variables. If they're not both in the same class, use global variables.

> **···**
>
> --  
> RMagick: [http://rmagick.rubyforge.org/](http://rmagick.rubyforge.org/)

---

<div class="post-metadata">

**Author:** ![Robert\_K1](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/robert_k1/32/1830_2.png) [@Robert\_K1](https://rubytalk.org/u/Robert_K1)\
**Post date:** [7 December 2007 13:28 UTC](https://rubytalk.org/t/dynamic-local-vars/42823/4 "2007-12-07T13:28:17Z")

</div>

> I wonder if there is any way to create local variables dynamically,  
> for example, given
> 
> def foo  
> &nbsp;&nbsp;bar  
> &nbsp;&nbsp;puts x, y  
> end
> 
> is it possible for bar to somehow create and initialize x and y?  
> Binding doesn't seem to be modifiable..

You cannot do this easily because of the method / variable ambiguity.  
There's a hack to do it: you need to define them before you use them  
but it is ugly and does not work properly.

14:23:17 ~  
$ ruby \<\<XXX

> def foo  
> x=y=nil  
> bar(binding)  
> puts x,y  
> end  
> def bar(b)  
> eval("x=1;y=2",b)  
> end  
> foo  
> XXX

1  
2

The problem with dynamically introducing local variables is that your  
code needs to be statically aware of them in order to use them. Even  
though you can inject any number of additional local variables into a  
binding, they won't get used because they do not appear in the code of  
that method.

A much better solution to the problem of storing dynamic values is a Hash.

def foo  
&nbsp;&nbsp;data = {}  
&nbsp;&nbsp;bar data  
&nbsp;&nbsp;puts data[:x], data[:y]  
end

def bar(x)  
&nbsp;&nbsp;x[:x] = 1  
&nbsp;&nbsp;x[:y] = 2  
end

But you can as well return multiple values

def foo  
&nbsp;&nbsp;x,y = bar  
&nbsp;&nbsp;puts x, y  
end

def bar  
&nbsp;&nbsp;return 1,2  
end

Kind regards

robert

> **···**
>
> 2007/12/7, Vasyl Smirnov \<vasyl.smirnov@gmail.com\>:
> 
> --  
> use.inject do |as, often| as.you\_can - without end

---

<div class="post-metadata">

**Author:** ![Vasyl\_Smirnov](https://avatars.discourse-cdn.com/v4/letter/v/ecc23a/32.png) [@Vasyl\_Smirnov](https://rubytalk.org/u/Vasyl_Smirnov)\
**Post date:** [7 December 2007 13:26 UTC](https://rubytalk.org/t/dynamic-local-vars/42823/5 "2007-12-07T13:26:18Z")

</div>

This would do, but I'd like to have the content of foo as simple as  
possible (that's actually the reason for the question).

> **···**
>
> On Dec 7, 11:35 am, MonkeeSage \<MonkeeS...@gmail.com\> wrote:
> 
> > On Dec 7, 2:19 am, Vasyl Smirnov \<vasyl.smir...@gmail.com\> wrote:
> > 
> > def bar  
> > &nbsp;&nbsp;x = 10  
> > &nbsp;&nbsp;y = 20  
> > &nbsp;&nbsp;binding  
> > end
> > 
> > def foo  
> > &nbsp;&nbsp;eval("puts x, y", bar)  
> > end

---

<div class="post-metadata">

**Author:** ![Vasyl\_Smirnov](https://avatars.discourse-cdn.com/v4/letter/v/ecc23a/32.png) [@Vasyl\_Smirnov](https://rubytalk.org/u/Vasyl_Smirnov)\
**Post date:** [7 December 2007 13:30 UTC](https://rubytalk.org/t/dynamic-local-vars/42823/6 "2007-12-07T13:30:28Z")

</div>

Yes, instance vars are an option. Though what would be better is  
something like a C-style macro,  
which would just define and assign these local vars inside foo. I  
thought maybe there's a way to do it in Ruby.

MonkeeSage and Tim, thank you both for your replies!

> **···**
>
> On Dec 7, 3:06 pm, Tim Hunter \<TimHun...@nc.rr.com\> wrote:
> 
> > Vasyl Smirnov wrote:  
> > \> Hi,
> > 
> > \> I wonder if there is any way to create local variables dynamically,  
> > \> for example, given
> > 
> > \> def foo  
> > \> bar  
> > \> puts x, y  
> > \> end
> > 
> > \> is it possible for bar to somehow create and initialize x and y?  
> > \> Binding doesn't seem to be modifiable..
> > 
> > \> Or am I asking too much? 🙂
> > 
> > Hmmm...local variables are called local because they're local to the  
> > method that uses them. A variable that's shared between two methods  
> > isn't local.
> > 
> > If foo and bar are both methods in the same class, use instance  
> > variables. If they're not both in the same class, use global variables.

---

<div class="post-metadata">

**Author:** ![Vasyl\_Smirnov](https://avatars.discourse-cdn.com/v4/letter/v/ecc23a/32.png) [@Vasyl\_Smirnov](https://rubytalk.org/u/Vasyl_Smirnov)\
**Post date:** [7 December 2007 13:47 UTC](https://rubytalk.org/t/dynamic-local-vars/42823/7 "2007-12-07T13:47:10Z")

</div>

> \> I wonder if there is any way to create local variables dynamically,  
> \> for example, given
> 
> \> def foo  
> \> bar  
> \> puts x, y  
> \> end
> 
> \> is it possible for bar to somehow create and initialize x and y?  
> \> Binding doesn't seem to be modifiable..
> 
> You cannot do this easily because of the method / variable ambiguity.  
> There's a hack to do it: you need to define them before you use them  
> but it is ugly and does not work properly.
> 
> 14:23:17 ~  
> $ ruby \<\<XXX\> def foo  
> \> x=y=nil  
> \> bar(binding)  
> \> puts x,y  
> \> end  
> \> def bar(b)  
> \> eval("x=1;y=2",b)  
> \> end  
> \> foo  
> \> XXX
> 
> 1  
> 2
> 
> The problem with dynamically introducing local variables is that your  
> code needs to be statically aware of them in order to use them. Even  
> though you can inject any number of additional local variables into a  
> binding, they won't get used because they do not appear in the code of  
> that method.

Thanks for clarifying that.

> A much better solution to the problem of storing dynamic values is a Hash.
> 
> def foo  
> &nbsp;&nbsp;data = {}  
> &nbsp;&nbsp;bar data  
> &nbsp;&nbsp;puts data[:x], data[:y]  
> end
> 
> def bar(x)  
> &nbsp;&nbsp;x[:x] = 1  
> &nbsp;&nbsp;x[:y] = 2  
> end
> 
> But you can as well return multiple values
> 
> def foo  
> &nbsp;&nbsp;x,y = bar  
> &nbsp;&nbsp;puts x, y  
> end
> 
> def bar  
> &nbsp;&nbsp;return 1,2  
> end

The hash approach is nice, and I actually use it for some other code.

I've posted this question because I wanted to eliminate the need to  
write "x, y = bar" and just go with "bar".  
The reason is that I have a bunch of methods, each starting with a  
kind of "x, y = bar", only with longer variable names.  
So it looked like it would be nice to somehow reduce them.

So, it looks like I should either a) stop whining about it, or b) use  
one of the proposed approaches.

> **···**
>
> On Dec 7, 3:28 pm, "Robert Klemme" \<shortcut...@googlemail.com\> wrote:
> 
> > 2007/12/7, Vasyl Smirnov \<vasyl.smir...@gmail.com\>:

---

<div class="post-metadata">

**Author:** ![Liam](https://avatars.discourse-cdn.com/v4/letter/l/b9e5f3/32.png) [@Liam](https://rubytalk.org/u/Liam)\
**Post date:** [7 December 2007 16:28 UTC](https://rubytalk.org/t/dynamic-local-vars/42823/8 "2007-12-07T16:28:01Z")

</div>

Do they need to be "variables"?

def bar(arg1,arg2)  
&nbsp;&nbsp;klass=class \<\< self; self; end  
&nbsp;&nbsp;klass.send(:define\_method,:x) { arg1 }  
&nbsp;&nbsp;klass.send(:define\_method,:y) { arg2 }  
end  
def foo  
&nbsp;&nbsp;bar(42,23)  
&nbsp;&nbsp;puts x,y  
end  
foo

Of course, x and y continue to exist after the scope of foo, but with a  
little more wrapping, you could solve that, too. You could create  
setters, but they'd have to be accessed like "self.x=".

> **···**
>
> On Fri, Dec 07, 2007 at 10:06:15PM +0900, Tim Hunter wrote:
> 
> > Hmmm...local variables are called local because they're local to the  
> > method that uses them. A variable that's shared between two methods  
> > isn't local.
> > 
> > If foo and bar are both methods in the same class, use instance  
> > variables. If they're not both in the same class, use global variables.

---

<div class="post-metadata">

**Author:** ![Jordan\_Callicoat](https://avatars.discourse-cdn.com/v4/letter/j/9de053/32.png) [@Jordan\_Callicoat](https://rubytalk.org/u/Jordan_Callicoat)\
**Post date:** [7 December 2007 14:15 UTC](https://rubytalk.org/t/dynamic-local-vars/42823/9 "2007-12-07T14:15:01Z")

</div>

Not so much like a C macro, but more like a C struct...you could...use  
a Struct 😉

V = Struct.new(:x, :y).new(nil, nil)

def bar  
&nbsp;&nbsp;V.x = 10  
&nbsp;&nbsp;V.y = 20  
end  
def foo  
&nbsp;&nbsp;bar  
&nbsp;&nbsp;puts V.x, V.y  
end

Regards,  
Jordan

> **···**
>
> On Dec 7, 7:47 am, Vasyl Smirnov \<vasyl.smir...@gmail.com\> wrote:
> 
> > On Dec 7, 3:28 pm, "Robert Klemme" \<shortcut...@googlemail.com\> wrote:
> > 
> > \> 2007/12/7, Vasyl Smirnov \<vasyl.smir...@gmail.com\>:
> > 
> > \> \> I wonder if there is any way to create local variables dynamically,  
> > \> \> for example, given
> > 
> > \> \> def foo  
> > \> \> bar  
> > \> \> puts x, y  
> > \> \> end
> > 
> > \> \> is it possible for bar to somehow create and initialize x and y?  
> > \> \> Binding doesn't seem to be modifiable..
> > 
> > \> You cannot do this easily because of the method / variable ambiguity.  
> > \> There's a hack to do it: you need to define them before you use them  
> > \> but it is ugly and does not work properly.
> > 
> > \> 14:23:17 ~  
> > \> $ ruby \<\<XXX\> def foo  
> > \> \> x=y=nil  
> > \> \> bar(binding)  
> > \> \> puts x,y  
> > \> \> end  
> > \> \> def bar(b)  
> > \> \> eval("x=1;y=2",b)  
> > \> \> end  
> > \> \> foo  
> > \> \> XXX
> > 
> > \> 1  
> > \> 2
> > 
> > \> The problem with dynamically introducing local variables is that your  
> > \> code needs to be statically aware of them in order to use them. Even  
> > \> though you can inject any number of additional local variables into a  
> > \> binding, they won't get used because they do not appear in the code of  
> > \> that method.
> > 
> > Thanks for clarifying that.
> > 
> > \> A much better solution to the problem of storing dynamic values is a Hash.
> > 
> > \> def foo  
> > \> data = {}  
> > \> bar data  
> > \> puts data[:x], data[:y]  
> > \> end
> > 
> > \> def bar(x)  
> > \> x[:x] = 1  
> > \> x[:y] = 2  
> > \> end
> > 
> > \> But you can as well return multiple values
> > 
> > \> def foo  
> > \> x,y = bar  
> > \> puts x, y  
> > \> end
> > 
> > \> def bar  
> > \> return 1,2  
> > \> end
> > 
> > The hash approach is nice, and I actually use it for some other code.
> > 
> > I've posted this question because I wanted to eliminate the need to  
> > write "x, y = bar" and just go with "bar".  
> > The reason is that I have a bunch of methods, each starting with a  
> > kind of "x, y = bar", only with longer variable names.  
> > So it looked like it would be nice to somehow reduce them.
> > 
> > So, it looks like I should either a) stop whining about it, or b) use  
> > one of the proposed approaches.

---

<div class="post-metadata">

**Author:** ![Vasyl\_Smirnov](https://avatars.discourse-cdn.com/v4/letter/v/ecc23a/32.png) [@Vasyl\_Smirnov](https://rubytalk.org/u/Vasyl_Smirnov)\
**Post date:** [7 December 2007 19:29 UTC](https://rubytalk.org/t/dynamic-local-vars/42823/10 "2007-12-07T19:29:30Z")

</div>

Actually, they whole thing has to be thread-safe and reentrant 🙂

> **···**
>
> On Dec 7, 6:28 pm, Liam \<ruby-t...@metacall.org\> wrote:
> 
> > On Fri, Dec 07, 2007 at 10:06:15PM +0900, Tim Hunter wrote:  
> > \> Hmmm...local variables are called local because they're local to the  
> > \> method that uses them. A variable that's shared between two methods  
> > \> isn't local.
> > 
> > \> If foo and bar are both methods in the same class, use instance  
> > \> variables. If they're not both in the same class, use global variables.
> > 
> > Do they need to be "variables"?
> > 
> > def bar(arg1,arg2)  
> > &nbsp;&nbsp;klass=class \<\< self; self; end  
> > &nbsp;&nbsp;klass.send(:define\_method,:x) { arg1 }  
> > &nbsp;&nbsp;klass.send(:define\_method,:y) { arg2 }  
> > end  
> > def foo  
> > &nbsp;&nbsp;bar(42,23)  
> > &nbsp;&nbsp;puts x,y  
> > end  
> > foo
> > 
> > Of course, x and y continue to exist after the scope of foo, but with a  
> > little more wrapping, you could solve that, too. You could create  
> > setters, but they'd have to be accessed like "self.x=".

---

<div class="post-metadata">

**Author:** ![Tim\_Hunter1](https://avatars.discourse-cdn.com/v4/letter/t/3ec8ea/32.png) [@Tim\_Hunter1](https://rubytalk.org/u/Tim_Hunter1)\
**Post date:** [7 December 2007 14:33 UTC](https://rubytalk.org/t/dynamic-local-vars/42823/11 "2007-12-07T14:33:36Z")

</div>

Jordan Callicoat wrote:

> Not so much like a C macro, but more like a C struct...you could...use  
> a Struct 😉
> 
> V = Struct.new(:x, :y).new(nil, nil)
> 
> def bar  
> &nbsp;&nbsp;V.x = 10  
> &nbsp;&nbsp;V.y = 20  
> end  
> def foo  
> &nbsp;&nbsp;bar  
> &nbsp;&nbsp;puts V.x, V.y  
> end
> 
> Regards,  
> Jordan

Of course the Struct is not actually allowing him to share data between  
bar and foo. It's the global constant V that's doing that.

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Jordan\_Callicoat](https://avatars.discourse-cdn.com/v4/letter/j/9de053/32.png) [@Jordan\_Callicoat](https://rubytalk.org/u/Jordan_Callicoat)\
**Post date:** [7 December 2007 15:50 UTC](https://rubytalk.org/t/dynamic-local-vars/42823/12 "2007-12-07T15:50:01Z")

</div>

Yeah. I thought it fit the desired behavior though, since it shortened  
the call to bar (as per desired behavior) and only adds four more  
chars ("V." twice) over the original example.

Regards,  
Jordan

> **···**
>
> On Dec 7, 8:33 am, Tim Hunter \<rmag...@gmail.com\> wrote:
> 
> > Jordan Callicoat wrote:
> > 
> > \> Not so much like a C macro, but more like a C struct...you could...use  
> > \> a Struct 😉
> > 
> > \> V = Struct.new(:x, :y).new(nil, nil)
> > 
> > \> def bar  
> > \> V.x = 10  
> > \> V.y = 20  
> > \> end  
> > \> def foo  
> > \> bar  
> > \> puts V.x, V.y  
> > \> end
> > 
> > \> Regards,  
> > \> Jordan
> > 
> > Of course the Struct is not actually allowing him to share data between  
> > bar and foo. It's the global constant V that's doing that.  
> > --  
> > Posted viahttp://www.ruby-forum.com/.

---

<div class="post-metadata">

**Author:** ![Robert\_K1](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/robert_k1/32/1830_2.png) [@Robert\_K1](https://rubytalk.org/u/Robert_K1)\
**Post date:** [8 December 2007 11:04 UTC](https://rubytalk.org/t/dynamic-local-vars/42823/13 "2007-12-08T11:04:59Z")

</div>

Global variables are considered harmful for a reason. Sometimes more explicitness is better. I.e. in this case I'd rather use multiple returns or - more likely - instance variables. But since I know nothing about the algorithm I cannot make a recommendation here. I'd just generally suggest to look at command pattern.

Kind regards

&nbsp;&nbsp;robert

> **···**
>
> On 07.12.2007 16:48, MonkeeSage wrote:
> 
> > On Dec 7, 8:33 am, Tim Hunter \<rmag...@gmail.com\> wrote:
> > 
> > > Jordan Callicoat wrote:
> > > 
> > > > Not so much like a C macro, but more like a C struct...you could...use  
> > > > a Struct 😉  
> > > > V = Struct.new(:x, :y).new(nil, nil)  
> > > > def bar  
> > > > &nbsp;&nbsp;V.x = 10  
> > > > &nbsp;&nbsp;V.y = 20  
> > > > end  
> > > > def foo  
> > > > &nbsp;&nbsp;bar  
> > > > &nbsp;&nbsp;puts V.x, V.y  
> > > > end  
> > > > Regards,  
> > > > Jordan
> > > 
> > > Of course the Struct is not actually allowing him to share data between  
> > > bar and foo. It's the global constant V that's doing that.  
> > > --  
> > > Posted viahttp://www.ruby-forum.com/.
> > 
> > Yeah. I thought it fit the desired behavior though, since it shortened  
> > the call to bar (as per desired behavior) and only adds four more  
> > chars ("V." twice) over the original example.

---

<div class="post-metadata">

**Author:** ![Jordan\_Callicoat](https://avatars.discourse-cdn.com/v4/letter/j/9de053/32.png) [@Jordan\_Callicoat](https://rubytalk.org/u/Jordan_Callicoat)\
**Post date:** [8 December 2007 13:15 UTC](https://rubytalk.org/t/dynamic-local-vars/42823/14 "2007-12-08T13:15:00Z")

</div>

Yeah, yeah...but it still fit (what was given) of the spec. 😛

Regards,  
Jordan

> **···**
>
> On Dec 8, 5:01 am, Robert Klemme \<shortcut...@googlemail.com\> wrote:
> 
> > On 07.12.2007 16:48, MonkeeSage wrote:
> > 
> > \> On Dec 7, 8:33 am, Tim Hunter \<rmag...@gmail.com\> wrote:  
> > \>\> Jordan Callicoat wrote:
> > 
> > \>\>\> Not so much like a C macro, but more like a C struct...you could...use  
> > \>\>\> a Struct 😉  
> > \>\>\> V = Struct.new(:x, :y).new(nil, nil)  
> > \>\>\> def bar  
> > \>\>\> V.x = 10  
> > \>\>\> V.y = 20  
> > \>\>\> end  
> > \>\>\> def foo  
> > \>\>\> bar  
> > \>\>\> puts V.x, V.y  
> > \>\>\> end  
> > \>\>\> Regards,  
> > \>\>\> Jordan  
> > \>\> Of course the Struct is not actually allowing him to share data between  
> > \>\> bar and foo. It's the global constant V that's doing that.  
> > \>\> --  
> > \>\> Posted viahttp://www.ruby-forum.com/.
> > 
> > \> Yeah. I thought it fit the desired behavior though, since it shortened  
> > \> the call to bar (as per desired behavior) and only adds four more  
> > \> chars ("V." twice) over the original example.
> > 
> > Global variables are considered harmful for a reason. Sometimes more  
> > explicitness is better. I.e. in this case I'd rather use multiple  
> > returns or - more likely - instance variables. But since I know nothing  
> > about the algorithm I cannot make a recommendation here. I'd just  
> > generally suggest to look at command pattern.
> > 
> > Kind regards
> > 
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;robert
