# Adding local variables via block

**URL:** <https://www.ruby-forum.com/t/adding-local-variables-via-block/86217>\
**Category:** Ruby\
**Created:** [February 20, 2007, 7:33pm UTC](https://www.ruby-forum.com/t/adding-local-variables-via-block/86217 "2007-02-20T19:33:37Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![dangermoose](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/e79b87/32.png) [@dangermoose](https://www.ruby-forum.com/u/dangermoose)\
**Post date:** [February 20, 2007, 7:33pm UTC](https://www.ruby-forum.com/t/adding-local-variables-via-block/86217/1 "2007-02-20T19:33:37Z")

</div>

Hi,

i’m a roob noob and I’m trying to grasp procs/blocks/etc.

specifically, I’d like to pass a piece of code into a method.

the piece of code will contain a variable name and an assignment

e.g.

####################

def lamb\_test

```
cond = 'hello'

yield

puts cond + ' ' + name

```

end

lamb\_test {name = ‘bob’}

###################

When I do this, I get the following error:

"undefined local variable or method `name’ for main:Object…

is it possible to define a local variable like this on the fly with  
blocks?

obviously, this is an oversimplified case but I want to be able to  
dynamically insert a local variable and an assignment to that variable  
into the “generic” function lamb\_test

Is there a better way?

TIA!

---

<div class="post-metadata">

**Author:** ![dangermoose](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/e79b87/32.png) [@dangermoose](https://www.ruby-forum.com/u/dangermoose)\
**Post date:** [February 20, 2007, 7:52pm UTC](https://www.ruby-forum.com/t/adding-local-variables-via-block/86217/2 "2007-02-20T19:52:38Z")

</div>

On 2/20/07, Paul D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> the piece of code will contain a variable name and an assignment
> 
> ###################  
> blocks?
> 
> obviously, this is an oversimplified case but I want to be able to  
> dynamically insert a local variable and an assignment to that variable  
> into the “generic” function lamb\_test
> 
> Is there a better way?

yield will return the value from the block it executes. Just have your  
block return the name ‘bob’ …

def lamb\_test  
cond = ‘hello’  
name = yield  
puts cond + ’ ’ + name  
end

lamb\_test { ‘bob’ } #=\> ‘hello bob’

In the more general case, you would need to use one of the ‘eval’  
methods in order to create a new local variable in a local namespace.  
However, (1) the ‘eval’ methods work only on strings and not blocks,  
and (2) they are mostly evil and should be handled with great care.

Blessings,  
TwP

---

<div class="post-metadata">

**Author:** ![dangermoose](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/e79b87/32.png) [@dangermoose](https://www.ruby-forum.com/u/dangermoose)\
**Post date:** [February 20, 2007, 7:54pm UTC](https://www.ruby-forum.com/t/adding-local-variables-via-block/86217/3 "2007-02-20T19:54:38Z")

</div>

Hi,

On Tuesday 20 February 2007 19:33, Paul D. wrote:

> ####################  
> def lamb\_test  
> cond = ‘hello’  
> yield  
> puts cond + ’ ’ + name  
> end
> 
> lamb\_test {name = ‘bob’}
> 
> ###################

the local variables defined in the block live only in the block’s scope.  
if a  
local variable is defined out of the block, a closure is made and you  
can  
access (and redefine) that variable in the block:

> > a = 1  
> > =\> 1
> 
> > p = proc { a = 2; b = 3 }  
> > =\> #Proc:0xb7ae7150@:8(irb)
> 
> > p.call  
> > =\> 2
> 
> > a  
> > =\> 2
> 
> > b  
> > =\> NameError: …

> Is there a better way?

well

def lamb\_test  
cond = ‘hello’  
name = yield  
puts cond + ’ ’ + name  
end

better:

def lamb\_test  
cond = hello  
puts cond + ’ ’ + yield  
end

better:

def lamb\_test  
puts [‘hello’, yield].join(’ ')  
end

even better:

def lamb\_test  
[‘hello’, yield].join(’ ')  
end

puts lamb\_test { ‘world’ }

if “puts” is not strictly necessary in your method, take it out, and  
just  
return a string. this way, when you need to print that string on  
something  
different than a text terminal, you don’t need to mess with the class  
you’ve  
written earlier.

HTH! 🙂

---

<div class="post-metadata">

**Author:** ![dangermoose](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/e79b87/32.png) [@dangermoose](https://www.ruby-forum.com/u/dangermoose)\
**Post date:** [February 20, 2007, 8:13pm UTC](https://www.ruby-forum.com/t/adding-local-variables-via-block/86217/4 "2007-02-20T20:13:41Z")

</div>

On Feb 20, 2007, at 12:52 PM, Tim P. wrote:

> In the more general case, you would need to use one of the ‘eval’  
> methods in order to create a new local variable in a local namespace.  
> However, (1) the ‘eval’ methods work only on strings and not blocks,  
> and (2) they are mostly evil and should be handled with great care.

eval() introduces a new scope, so local variables created in that  
context do not leak into the calling scope:

> > def test\_eval  
> > eval(“name = ‘James’”, binding)  
> > name  
> > end  
> > =\> nil
> 
> > tes  
> > test test\_eval
> 
> > test\_eval  
> > NameError: undefined local variable or method `name' for main:Object from (irb):3:in`test\_eval’  
> > from (irb):5  
> > from :0

James Edward G. II

---

<div class="post-metadata">

**Author:** ![dangermoose](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/e79b87/32.png) [@dangermoose](https://www.ruby-forum.com/u/dangermoose)\
**Post date:** [February 20, 2007, 9:11pm UTC](https://www.ruby-forum.com/t/adding-local-variables-via-block/86217/5 "2007-02-20T21:11:57Z")

</div>

Hi –

On Wed, 21 Feb 2007, Tim P. wrote:

> In the more general case, you would need to use one of the ‘eval’  
> methods in order to create a new local variable in a local namespace.  
> However, (1) the ‘eval’ methods work only on strings and not blocks,  
> and (2) they are mostly evil and should be handled with great care.

Actually the only one that works only on strings is eval.  
instance\_eval and class\_eval work on blocks too.

David

---

<div class="post-metadata">

**Author:** ![dangermoose](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/e79b87/32.png) [@dangermoose](https://www.ruby-forum.com/u/dangermoose)\
**Post date:** [February 20, 2007, 9:03pm UTC](https://www.ruby-forum.com/t/adding-local-variables-via-block/86217/6 "2007-02-20T21:03:53Z")

</div>

On 2/20/07, James Edward G. II [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> eval() introduces a new scope, so local variables created in that  
> context do not leak into the calling scope:

I am not recommending this, but you can force a binding into an eval.  
However, due to how the Ruby parser identifies local variables, they  
need to be referenced in “code” before you can use them normally.

def foo(binding)  
eval(“x = 42”, binding)  
end

foo(binding)  
x = x  
puts “x = #{x}”

Good luck  
pth

---

<div class="post-metadata">

**Author:** ![dangermoose](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/e79b87/32.png) [@dangermoose](https://www.ruby-forum.com/u/dangermoose)\
**Post date:** [February 20, 2007, 9:12pm UTC](https://www.ruby-forum.com/t/adding-local-variables-via-block/86217/7 "2007-02-20T21:12:57Z")

</div>

Hi,

On Tuesday 20 February 2007 21:02, Patrick H. wrote:

> I am not recommending this, but you can force a binding into an eval.  
> However, due to how the Ruby parser identifies local variables, they  
> need to be referenced in “code” before you can use them normally.

my irb disagrees:

vjt@neutrino:~$ irb  
/home/vjt| irb(main):001:0\> eval ‘x = 42’, binding  
42  
/home/vjt| irb(main):002:0\> x  
42  
/home/vjt| irb(main):003:0\> RUBY\_VERSION  
“1.8.5”  
/home/vjt| irb(main):004:0\>

---

<div class="post-metadata">

**Author:** ![dangermoose](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/e79b87/32.png) [@dangermoose](https://www.ruby-forum.com/u/dangermoose)\
**Post date:** [February 20, 2007, 9:14pm UTC](https://www.ruby-forum.com/t/adding-local-variables-via-block/86217/8 "2007-02-20T21:14:58Z")

</div>

On Wed, 21 Feb 2007, Marcello B. wrote:

> /home/vjt| irb(main):001:0\> eval ‘x = 42’, binding  
> 42  
> /home/vjt| irb(main):002:0\> x  
> 42  
> /home/vjt| irb(main):003:0\> RUBY\_VERSION  
> “1.8.5”  
> /home/vjt| irb(main):004:0\>

try writing that in a script. in irb you are **already** in eval.  
google the  
archives for more info.

cheers.

-a

---

<div class="post-metadata">

**Author:** ![dangermoose](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/e79b87/32.png) [@dangermoose](https://www.ruby-forum.com/u/dangermoose)\
**Post date:** [February 20, 2007, 9:28pm UTC](https://www.ruby-forum.com/t/adding-local-variables-via-block/86217/9 "2007-02-20T21:28:00Z")

</div>

Hi,

On Tuesday 20 February 2007 21:14, removed\_email\_address@domain.invalid wrote:

> > vjt@neutrino:~$ irb  
> > /home/vjt| irb(main):001:0\> eval ‘x = 42’, binding  
> > 42  
> > /home/vjt| irb(main):002:0\> x  
> > 42  
> > /home/vjt| irb(main):003:0\> RUBY\_VERSION  
> > “1.8.5”  
> > /home/vjt| irb(main):004:0\>
> 
> try writing that in a script.

vjt@neutrino:~$ ruby -e “eval(‘x=42’,binding); x”  
-e:1: undefined local variable or method `x’ for main:Object (NameError)

> in irb you are **already** in eval. google the archives for more info.

gotcha! 🙂 thanks
