MxLDevs
MxLDevs

Reputation: 19506

Get current value that a global variable is pointing to

I have some code written like this

$var1 = 2
$var2 = 4
...

keywords = {"one" => $var1, "two" => $var2, ...}

The problem is that I want to get the value stored in that variable when I hash into keywords, but ruby doesn't seem to be re-evaluating the variables when I need them. So if $var1 was changed during execution, keywords["one"] still returns the original value of 2

How can I change the hash so that I will first determine which variable I need to access, and then go and grab its value?

There are quite a number of global variables (they didn't use array?), and I don't want to have redundant case/when or if/elsif blocks.

EDIT: A more precise question would be

"How do I retrieve the value that a variable is currently pointing to?"

Upvotes: 2

Views: 593

Answers (2)

Paul Rubel
Paul Rubel

Reputation: 27222

In general this seems like a bad idea. Instead of updating $var1 just update the hash and always access $var1 through keywords["one"]

You could use eval, but it's not a good solution:

$var1 = 2
$var2 = 4
...
keywords = {"one" => "$var1", "two" => "$var2", ...}
$var1 = 6
var1 = eval(keywords["one"])  # -> 6

Update: Note that the eval will take any code you pass in and execute it. You need to be very careful that the thing you're evaling is of the form you expect. It can be a big security risk.

Upvotes: 3

Phrogz
Phrogz

Reputation: 303206

Variables do not contain values, they reference them. When you write:

foo = 2
bar = [foo]
foo = 4

…it does not cause bar to be [4]. What ~happens is:

  1. Create a value 2 in memory and set the variable foo to reference it.
  2. Create a new array whose first slot references the value referenced by foo (i.e. 2), and set the variable bar to reference that array.
  3. Create a value 4 in memory and change the variable foo to reference it instead.

Some object types that are mutable. For example, you can change the actual contents of a String or an Array to be different. In this case, all references to that value reflect the change:

foo = "hello"
bar = [foo]
foo[0] = "j"
p bar        #=> ["jello"]

Numbers are not mutable, however. If you want to have a 'handle' to a number than you can change and have all other references to that number change, you will need to wrap the number in a mutable data type. For example:

$var1 = [2]
keywords = { "one"=>$var1 }
p keywords["one"][0] #=> 2
$var1[0] = 4
p keywords["one"][0] #=> 4

Now, if your values are not numbers, but are strings (as "keywords" implies) then you can mutate and wholly replace those:

$var1 = "foo"
keywords = { "one"=>$var1 }
$var1.replace( "bar" )
p keywords["one"]           #=> "bar"

The key is that you must be calling a method on the object itself (and that method must change the object itself, not return a new object); you cannot make this work using variable assignment. For example, see String#replace.

Upvotes: 1

Related Questions