# Eval question

**URL:** <https://www.ruby-forum.com/t/eval-question/75632>\
**Category:** Ruby\
**Created:** [November 11, 2006, 6:44pm UTC](https://www.ruby-forum.com/t/eval-question/75632 "2006-11-11T18:44:08Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![splattael](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/858c86/32.png) [@splattael](https://www.ruby-forum.com/u/splattael)\
**Post date:** [November 11, 2006, 6:44pm UTC](https://www.ruby-forum.com/t/eval-question/75632/1 "2006-11-11T18:44:08Z")

</div>

Hi,

I am setting up a few variables based on user input with the following  
code snippet:

==================================  
vars = %w{a b c}

vars.each do |var|  
print “#{var} = "  
val = gets  
eval(”$#{var}=#{val.chomp}")  
end

# #use a, b, c here for something

What I don’t like about this code is the use of global variables.  
However, I have to use them - or otherwise a,b,c will be already out of  
scope at the place I need them.

Another possibility would be to use constants, i.e.

vars = %w{A B C}

which would work well - however, since I am repeating the process more  
times, from the second iteration on I am getting warnings that A, B, C  
etc were already initialized, which is not nice.

I guess yet another possibility would be to wrap a class around this  
stuff and use instance\_eval or something like that - but a class that  
serves solely this purpose looks to heavy to me…

Any other ideas?

TIA,  
Peter

\_\_  
[http://www.rubyrailways.com](http://www.rubyrailways.com)

---

<div class="post-metadata">

**Author:** ![splattael](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/858c86/32.png) [@splattael](https://www.ruby-forum.com/u/splattael)\
**Post date:** [November 11, 2006, 8:10pm UTC](https://www.ruby-forum.com/t/eval-question/75632/2 "2006-11-11T20:10:20Z")

</div>

Hey Joel, that looks great! Thanks a lot (for solving the mystery of the  
sprintf problem, too 🙂

---

<div class="post-metadata">

**Author:** ![splattael](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/858c86/32.png) [@splattael](https://www.ruby-forum.com/u/splattael)\
**Post date:** [November 11, 2006, 8:04pm UTC](https://www.ruby-forum.com/t/eval-question/75632/3 "2006-11-11T20:04:19Z")

</div>

Peter S. wrote:

> val = gets  
> eval("$#{var}=#{val.chomp}")  
> end
> 
> # #use a, b, c here for something
> 
> What I don’t like about this code is the use of global variables.  
> However, I have to use them - or otherwise a,b,c will be already out of  
> scope at the place I need them.

Use a hash?

vars = {  
“a” =\> nil,  
“b” =\> nil,  
“c” =\> nil,  
}

def get\_input vars  
vars.keys.each do |var|  
print “#{var} = "  
val = gets  
vars[var] = val.chomp  
eval(”$#{var}=#{val.chomp}")  
end  
end

get\_input vars  
p vars  
**END**  
a = 1  
b = 2  
c = 3  
{“a”=\>“1”, “b”=\>“2”, “c”=\>“3”}

You can use instance\_eval with the hash, as you suggested:

module AcessibleKeys  
def method\_missing(m, \*rest)  
if rest.empty?  
fetch(m.to\_s)  
else  
super  
end  
end  
end

vars.extend AcessibleKeys

get\_input vars  
p vars

vars.instance\_eval do  
puts “a+b+c = #{a+b+c}”  
end  
**END**  
a = 1  
b = 2  
c = 3  
{“a”=\>“1”, “b”=\>“2”, “c”=\>“3”}  
a+b+c = 123

---

<div class="post-metadata">

**Author:** ![splattael](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/858c86/32.png) [@splattael](https://www.ruby-forum.com/u/splattael)\
**Post date:** [November 11, 2006, 9:12pm UTC](https://www.ruby-forum.com/t/eval-question/75632/4 "2006-11-11T21:12:31Z")

</div>

Peter S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> val = gets  
> Another possibility would be to use constants, i.e.
> 
> Any other ideas?

Pass a binding?

a = 1  
b = 2  
c = 3

def goforit(w, bind)  
w.each do |v|  
eval(“#{v} = ‘heehee’”, bind)  
end  
end

goforit %w{a b c}, binding  
puts a, b, c

m.

---

<div class="post-metadata">

**Author:** ![splattael](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/858c86/32.png) [@splattael](https://www.ruby-forum.com/u/splattael)\
**Post date:** [November 12, 2006, 10:03am UTC](https://www.ruby-forum.com/t/eval-question/75632/5 "2006-11-12T10:03:27Z")

</div>

On 11/11/06, Peter S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> print "#{var} = "
> 
> serves solely this purpose looks to heavy to me…
> 
> Any other ideas?
> 
> TIA,  
> Peter

Just two tiny improvements

- Do not use globals
- Do not use eval  
#!/usr/bin/ruby

vars = %w{a b c}

vars.each do |var|  
print "#{var} = "  
val = gets.chomp  
instance\_variable\_set “@#{var}”, val  
end

puts “a = #{@a}”

Maybe you prefer this?  
But if you want to access the instance variables by name you can also  
define  
an attribute\_reader/writer/accessor inside the vars.each loop.

Cheers  
Robert

\_\_

> [http://www.rubyrailways.com](http://www.rubyrailways.com)

–  
The reasonable man adapts himself to the world; the unreasonable one  
persists in trying to adapt the world to himself. Therefore all progress  
depends on the unreasonable man.

- George Bernard Shaw
