No Pugs

they're evil

ruby oddity with creating local variables dynamically using eval

It seems that you cannot create a local variable dynamically in ruby using eval with a binding.

Here’s an example from an IRB session:

irb(main):001:0> def make_a(b)
irb(main):002:1>   eval "a = 'this is a!'", b
irb(main):003:1> end
=> nil
irb(main):004:0> a
NameError: undefined local variable or method `a' for main:Object
        from (irb):4
        from :0
irb(main):005:0> make_a(binding)
=> "this is a!"
irb(main):006:0> a
=> "this is a!"
irb(main):007:0> def test_a
irb(main):008:1>   a = 10
irb(main):009:1>   make_a(binding)
irb(main):010:1>   puts a
irb(main):011:1> end
=> nil
irb(main):012:0> test_a
this is a!
=> nil
irb(main):013:0> def test_a
irb(main):014:1>   make_a(binding)
irb(main):015:1>   puts a
irb(main):016:1> end
=> nil
irb(main):017:0> test_a
NameError: undefined local variable or method `a' for main:Object
        from (irb):15:in `test_a'
        from (irb):17
        from :0
irb(main):018:0>

The last NameError in that IRB session makes no sense to me. I have tried this in Ruby 1.8.6 and in Ruby 1.9.1 and both give the same result.

Can somebody explain what is going on here? Are there any known workarounds for this? I was trying to DRY up some particularly repetitive code, part of which involves initializing a local variable, when I stumbled upon this. I’m having trouble finding blog posts that explain this unexpected behavior, and none of the official documentation that I’ve looked at for Binding and eval seem to point out that you cannot declare local variable in such a manner.

Here’s a stripped down version of the code if you want to put it in your own IRB session and play with it:


 def make_a(b)
   eval "a = 'this is a!'", b
 end
 a
 make_a(binding)
 a
 def test_a
   a = 10
   make_a(binding)
   puts a
 end
 test_a
 def test_a
   make_a(binding)
   puts a
 end
 test_a

Published on 03/10/2010 at 02:29PM under .

  • By KL 11/05/2010 at 09:12AM

    If you’re testing “eval” (and probably methods like “instance_eval”) in IRB, you won’t get an accurate picture of how the same code would behave in a script.

    See: http://www.ruby-forum.com/topic/155673

    http://stackoverflow.com/questions/715010/ruby-eval-behaves-differently-in-irb-versus-in-a-file

    When I run your code as a script (after putting appropriate rescue’s), the only call that succeeds is the 1st call of test_a.


  • By miles 11/05/2010 at 08:39PM

    Ahhhhh, interesting. Thank you very much, KL, for the explanation. I never even thought to try it as a script to see if there was a different behavior.


  • By Ff 06/29/2011 at 03:15AM

    On page 559 “Programing Ruby 1.9” by Dave Thomas et al you can find an example…..

    “Local variables assigned within eval are available after eval only if they were defined outside of eval”


  • By miles 07/02/2011 at 05:50PM

    Thanks for the information, Ff!


Comment ruby oddity with creating local variables dynamically using eval

Powered by Typo – Thème Frédéric de Villamil | Photo Glenn