Eval question

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

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

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

Peter S. [email protected] 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.

On 11/11/06, Peter S. [email protected] 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


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