Forum: Ruby Variable Generation

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
425cab08658a06567879717de154552c?d=identicon&s=25 Ari Brown (Guest)
on 2007-07-23 23:21
(Received via mailing list)
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
F3b02532d4cb4855881935c002389213?d=identicon&s=25 Morton Goldberg (Guest)
on 2007-07-23 23:53
(Received via mailing list)
On Jul 23, 2007, at 5:19 PM, Ari Brown 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
289cf19aa581c445915c072bf45c5e25?d=identicon&s=25 Todd Benson (Guest)
on 2007-07-23 23:57
(Received via mailing list)
On 7/23/07, Ari Brown <ari@aribrown.com> 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
B57c5af36f5c1f33243dd8b2dd9043b1?d=identicon&s=25 F. Senault (Guest)
on 2007-07-24 00:36
(Received via mailing list)
Le 23 juillet 2007 à 23:19, Ari Brown 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...  :)

Fred
6087a044557d6b59ab52e7dd20f94da8?d=identicon&s=25 Peña, Botp (Guest)
on 2007-07-24 04:19
(Received via mailing list)
From: Ari Brown [mailto:ari@aribrown.com]
# 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
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2007-07-24 11:09
(Received via mailing list)
2007/7/23, Ari Brown <ari@aribrown.com>:
>
> 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
This topic is locked and can not be replied to.