Variable Generation


#1

yes, I mean spontaneously generated variables.

Assume we have an array:
array = %w(yea cool awesome stuff)
Now, I’m looking to make a variable corresponding to the item. so that:

yea = “yea”
cool = “cool”
awesome = “awesome”
stuff = “stuff”

My current method (which FAILS) is using eval
array.each {|item| eval(item + “=”#{item}"") }

I tested this with a puts instead of eval, and it comes out exactly
as it should. But when I try to use the variable, I get a
undefined local variable or method
error.

Bwah?
-------------------------------------------------------|
~ Ari
crap my sig won’t fit


#2

On Jul 23, 2007, at 5:19 PM, Ari B. wrote:

stuff = “stuff”

My current method (which FAILS) is using eval
array.each {|item| eval(item + “=”#{item}"") }

I tested this with a puts instead of eval, and it comes out exactly
as it should. But when I try to use the variable, I get a undefined
local variable or method error.

Your problem likely results from the scoping rules for local
variables. I think it would work as you expect if you used global or
instance variables. However, for this kind of thing, I usually prefer
a hash. You might consider using something like:

WORDS = %w(yea cool awesome stuff)
DICTIONARY = {}
WORDS.each { |w| DICTIONARY[w.to_sym] = w }
DICTIONARY[:cool] # => “cool”

Regards, Morto


#3

On 7/23/07, Ari B. removed_email_address@domain.invalid wrote:

My current method (which FAILS) is using eval
array.each {|item| eval(item + “=”#{item}"") }

I tested this with a puts instead of eval, and it comes out exactly
as it should. But when I try to use the variable, I get a
undefined local variable or method
error.

Bwah?

Your new variables only have scope within the block.

I suppose you could do use global variables:

irb> a = %w{ yea cool awesome stuff }
=> [“yea”, “cool”, “awesome”, “stuff”]
irb> a.each { |elem| eval("$" + elem + “=”#{elem}"") }
=> [“yea”, “cool”, “awesome”, “stuff”]
irb> $yea
=> “yea”

Yuck. Is there some reason you couldn’t just use a hash, maybe?

irb> h = {}
=> {}
irb> %w{ yea cool awesome stuff }.each { |e| h[e.intern] = e }
=> [“yea”, “cool”, “awesome”, “stuff”]
irb> h[:yea]
=> “yea”

Todd


#4

Le 23 juillet 2007 à 23:19, Ari B. a écrit :

My current method (which FAILS) is using eval
array.each {|item| eval(item + “=”#{item}"") }

When the eval is run, you’re in the context of the block. If the
variable exists beforehand, you can use it. Otherwise, I don’t know if
it can be done.

You can try to make an accessor method, though :

[ ‘a’, ‘b’, ‘c’ ].each do |t| eval <<-EOE
def #{t}
‘#{t}’
end
EOE
end
puts a
puts b

On the other hand, you can always use instance variables, with the
following code for instance :

[ ‘a’, ‘b’, ‘c’ ].each do |t|
self.instance_variable_set("@#{t}".to_sym, t)
end
puts @a
puts @b

In some contexts, I guess you could also call attr_accessor to generate
the accessors, but I can’t wrap my mind around it at this hour… :slight_smile:

Fred


#5

2007/7/23, Ari B. removed_email_address@domain.invalid:

My current method (which FAILS) is using eval
array.each {|item| eval(item + “=”#{item}"") }

I tested this with a puts instead of eval, and it comes out exactly
as it should. But when I try to use the variable, I get a
undefined local variable or method
error.

There are various issues to your approach, namely that you cannot
reference local variables that are defined in an eval block and not
defined in the code around it. Ruby needs to read the variable name
literally if you want do access it. You cannot do something like

some_magic_that_sets_x()
puts x

Your probably is probably better solved by either using a Hash or
using OpenStruct.

Kind regards

robert


#6

From: Ari B. [mailto:removed_email_address@domain.invalid]

yes, I mean spontaneously generated variables.

you don’t like Struct

irb(main):006:0> v = Struct.new(:yea, :cool, :awesome, :stuff)
=> #Class:0xb7dd9048
irb(main):007:0> v1 = v.new(“yeah”,“cool”,“awesome”,“stuff”)
=> #<struct #Class:0xb7dd9048 yea=“yeah”, cool=“cool”,
awesome=“awesome”, stuff=“stuff”>
irb(main):008:0> v1.yea
=> “yeah”
irb(main):009:0> v1.yea = “heheh”
=> “heheh”
irb(main):010:0> v1.yea
=> “heheh”
irb(main):011:0> v2 = v.new(“yeah”,“cool”,“awesome”,“stuff”)
=> #<struct #Class:0xb7dd9048 yea=“yeah”, cool=“cool”,
awesome=“awesome”, stuff=“stuff”>
irb(main):012:0> v2.yea
=> “yeah”

you can play w your var groups …

irb(main):014:0> v3 = v1
=> #<struct #Class:0xb7dd9048 yea=“heheh”, cool=“cool”,
awesome=“awesome”, stuff=“stuff”>
irb(main):015:0> v3.yea
=> “heheh”

but i wish Struct vars or basically ruby’s accessors can be initialized,
like

v = Struct.new(:yea = “yeah!”, :cool = “cool”, :awesome = “!”, :stuff =
“:)” )

less repitition ie.

kind regards -botp