10

I am trying to dynamically create local variables in Ruby using eval and mutate the local-variables array. I am doing this in IRB.

eval "t = 2"
local_variables # => [:_]
eval "t"
# => NameError: undefined local variable or method `t' for main:Object
local_variables << "t".to_sym # => [:_, :t]
t
# => NameError: undefined local variable or method `t' for main:Object
2
  • 2
    Why are you trying to do that? What's the purpose? Commented Jul 24, 2013 at 19:10
  • @SergioTulentsev i asked myself exactly the same question. Most probably the original problem can be solved in a much simpler way. Commented Jul 24, 2013 at 19:15

3 Answers 3

17

You have to synchronize the evaluations with the same binding object. Otherwise, a single evaluation has its own scope.

b = binding
eval("t = 2", b)
eval("local_variables", b) #=> [:t, :b, :_]
eval("t", b) # => 2
b.eval('t') # => 2
Sign up to request clarification or add additional context in comments.

14 Comments

Thanks. How do I get the binding for main Object. Everytime you run b = binding; it gives back a different binding object.
@ppone: again, what are you trying to accomplish with that?
He means why you are trying to dynamically set local variables at all. Your problem can probably be solved differently, without setting local variables dynamically and, above all, without using eval.
I was just curious why it was not getting set. Your probably right there is a more efficient way to do it. Getting an answer to this question, helps me understand Ruby somewhat better.
I still don't see an answer anywhere here as to how, in general, to dynamically create a local variable in the existing context/binding, since binding always creates a new context.
|
13

You have to use the correct binding. In IRB for example this would work:

irb(main):001:0> eval "t=2", IRB.conf[:MAIN_CONTEXT].workspace.binding
=> 2
irb(main):002:0> local_variables
=> [:t, :_]
irb(main):003:0> eval "t"
=> 2
irb(main):004:0> t
=> 2

2 Comments

What about out of IRB? ruby myfile.rb?
@SergioTulentsev I'm not sure, TOPLEVEL_BINDING and other binding instances in ObjectSpace don't seem to work.
8

You could set instance variables like this:

instance_variable_set(:@a, 2)
@a
#=> 2

3 Comments

The question is not about instance variables.
That's true but maybe this could also solve the problem the OP has. As already said in my comment on the original question, i expect a much simpler solution to be feasible for the original problem.
also as an alternative method don't forget about define_method.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.