1

I'm trying to generate a bunch of variables that will be operated on. Started with 2 variables, 4, 8,16 and its about time I put the variable generation in a loop.

The variable is acting as a storage for the index of an array.

So a thread wakes up, picks up a variable and says "variable_0" is the first index, and stores location 24 inside of it.

This is usually done like so. This variable goes on and is used multiple times later on.

variable_0 = get_index(threadid)

Once I have 16 of such variables, its a pain and ugly to see that line repeated more than once. So I thought I'd put in a loop and tried it with 2 methods.

1. EVAL

for i in 0..15 do 
    eval("variable_#{i} = get_index(threadid)")
end

Does not work at all.

2. instance_variable_set

for i in 0..15 do
    index_name = "variable_#{i}"
    index_val = get_index(threadid)
    instance_variable_set("#{index_name}", :index_val)
end

This doesn't work either, since a later statement prints "variable not found " pretty much.

Is there a good way to go about doing this?

Due to restrictions later down the line, I cannot use an array for this, each variable has to be constructed as a single variable, so no arrays or anything like that would work

John Nikolaou
  • 161
  • 1
  • 10
  • 2
    This is a common XY-problem asked repeatedly. You should use an array to keep all the values. – sawa Feb 24 '16 at 16:23
  • Variables are used by external software, it doesn't take in array elements. I mean I wrote this above as well, its a limitation I can't overcome, its not my own unwillingness to work with arrays.... – John Nikolaou Feb 24 '16 at 16:26
  • But you seem to have freedom with variable naming (local or instance). It is a strange situation that you nevertheless do not have freedom of using an array. Your situation is not clear. – sawa Feb 24 '16 at 16:28
  • By the way, how does it make sense to have a variable name restricted to certain a format by an external software? Especially, local variables' scope is the method body or a block. I can't imagine a situation where you are calling an external software from Ruby, and the (local) variable name matters. – sawa Feb 24 '16 at 16:33
  • 1
    Can I ask why you want to have a set of variables containing a counter instead of just an array? Why is @variable_0 better than @variables[0]? – AJFaraday Feb 24 '16 at 16:34
  • Variable is passed to an external ruby function which then calls java. Attempting to pass an element of an array to the functions produces an error. – John Nikolaou Feb 24 '16 at 16:40
  • 2
    @JohnNikolaou that doesn't make much sense. You are passing the object that is assigned to the variable, not the variable itself. Therefore, it is irrelevant if the object is assigned to a variable or element of an array. – Stefan Feb 24 '16 at 16:42

2 Answers2

3

As others have pointed out it is not possible to create local variables dynamically in Ruby, you could set up a binding as well if you're looking for another method of achieving this.

With eval

b = binding
10.times do |i|
  eval("var#{i} = 'foo'", b)
end

> eval("var1", b)
=> "foo"

> eval("local_variables", b)
=> [:var9, :var8, :var7, :var6, :var5, :var4, :var3, :var2, :var1, :var0, :b, :_]

Without eval

b = binding
10.times do |i|
  b.local_variable_set("var#{i}", 'foo')
end

> b.local_variable_get('var1')
=> "foo"

> b.local_variables
=> [:var9, :var8, :var7, :var6, :var5, :var4, :var3, :var2, :var1, :var0, :b, :_]
Nabeel
  • 2,272
  • 1
  • 11
  • 14
2

Your second example is almost valid. You forgot @ for instance variable name and you passed a symbol as value instead the value itself.

for i in 0..15 do
  index_val = "some value #{i}"
  instance_variable_set("@variable_#{i}", index_val)
end

puts @variable_4 # "some value"

https://repl.it/BnLO/6

Krule
  • 6,468
  • 3
  • 34
  • 56
  • 1
    This is a terrible pattern, you should have answered something that would help the OP to do better code, like creating an array of values and operation on them. – jturolla Feb 24 '16 at 16:28
  • True that. But poster has expressed that `Array` can't be used. Who am I to judge? – Krule Feb 24 '16 at 16:29
  • You don't need the colon in `:"@variable_#{i}"`. The method accepts strings as well as symbols. – sawa Feb 24 '16 at 16:29
  • Thank you @sawa, corrected. – Krule Feb 24 '16 at 16:30
  • @jturolla Yes, this is terrible pattern, but he ask a question and this is correct answer. Ofc, better way is to use `Hash` or `Array`. – Lukas Baliak Feb 24 '16 at 16:31
  • This works for me, thanks, I do try to write as good code as possible and to improve, but when you're given a very strict external non-modifiable framework, you try to survive – John Nikolaou Feb 24 '16 at 16:32