Assigning a local variable whose name is given as a string

80 views Asked by At

Within this itteration:

a1=[1,2,3,4,5]
a2=[1,2,3,4,5]
a1.each_with_index{|a, i| ... = a + a2[i]}

I want to assign to different local variables b1, b2, ..., b5, each per iteration to get:

b1 # => 2
b2 # => 4
b3 # => 6
b4 # => 8
b5 # => 10

I tried:

a1.each_with_index{|a, i| ('b' + i.to_s) = a + a2[i]}

but this doesn't work. Anyone got any ideas?

4

There are 4 answers

1
Bejan George On
2
Simone Carletti On

What you are trying to do (dynamically creating local variables) doesn't make a lot of sense to me. Why don't you just use an array.

a1=[1,2,3,4,5]
a2=[1,2,3,4,5]

a1.zip(a2).inject([]) { |b, (x1, x2)| b << x1 + x2 }

=> [2, 4, 6, 8, 10]

You will achieve the same result. The item in position b[0] will be the sum of a1[0] + a2[0].

There is no easy way to dynamically define a local variable exactly because it does not make a lot of sense. In fact, you will have hard time trying to use those variables anywhere because your code will depend on runtime generated variables.

In other words, how would you ever be able to use b4, if you don't even know if b4 was ever generated. That's why an array is more convenient, you can know the size of the array and access all its items.

You can generate a local variable using eval, but as I said, it's definitely not the best approach.

0
Jörg W Mittag On

You can use Binding#local_variable_set to set already existing local variables. However, when you use it to set a new local variable (IOW to define one), the new local variable will be defined inside the Binding object but not the outside Binding you created it from.

The same thing happens with eval. Up to Ruby 1.8, eval leaked local variables to the outside scope, but that leak was plugged with Ruby 1.9.

In short, what you want is not possible.

0
Michel Antoine On

You have to use a Binding object.

a1=[1,2,3,4,5]
a2=[1,2,3,4,5]
b = binding()
a1.each_with_index{ |a, i| eval("b#{i + 1} = #{a + a2[i]}", b) }
(1..5).each do |i|
    eval("puts b#{i}", b)   
end

Now that the local variable is set you will be able to access it through that binding.

You can see an example HERE