|
Prev: implementing a simple and efficient index system
Next: rubygems won't run on WinXP after system update
From: Ib Lis on 6 Jul 2008 16:08 Hi I'm new to Ruby. Coming from Perl I really do enjoy the syntax and... irb. When I load a file, classes are loaded but not the variables set in the file. My file ends like that : fields = Set.new bibfile.each do | entry | entry.properties.keys.each do | field | fields << field end end p fields After load, irb prints the value of fields but the variable is not in scope : >> load 'bibtest.2.rb' #<Set: {:booktitle, :volume, :pages, :issn, :note, :ps, :number, :author, :custom, :year, :title, :journal}> => true >> fields NameError: undefined local variable or method `fields' for main:Object Thanks in advance for any hints -- Posted via http://www.ruby-forum.com/.
From: Joel VanderWerf on 6 Jul 2008 17:11 Ib Lis wrote: > Hi > I'm new to Ruby. Coming from Perl I really do enjoy the syntax and... > irb. > > When I load a file, classes are loaded but not the variables set in the > file. Normally(*) in ruby you can't get at the local vars in a file: $ cat x.rb x = 4 $ ruby -e 'eval File.read("x.rb"); p x' -e:1: undefined local variable or method `x' for main:Object (NameError) However, irb is a little different from ruby: $ irb irb(main):001:0> eval File.read("x.rb"); x NameError: undefined local variable or method `x' for main:Object from (irb):1 irb(main):002:0> x => 4 Note that x is undefined if you use it in the same line that defines it, but x is defined thereafter. This is because irb parses the whole line at a time before executing it. After the eval, x is defined in irb's scope. That's special to irb--doing the same eval in a separate file doesn't work: $ cat y.rb eval File.read("x.rb") p x $ ruby y.rb y.rb:2: undefined local variable or method `x' for main:Object (NameError) ------------------------- (*) However: $ cat x2.rb x = 4 $scope = proc{} $ ruby -e 'eval File.read("x2.rb"); p eval("x", $scope)' 4 The global is just one way to break out of the scope of the file. You could also use a constant. The global might be best if you are just doing this interactively. If you need to load files from a program, and keep their instance (not local) variables, constants, and methods in separate scopes, you might be interested in these: http://raa.ruby-lang.org/project/script/ http://raa.ruby-lang.org/project/dynaload/ -- vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
From: عمر ملقب بالثانی on 6 Jul 2008 18:59 Thanks a lot. Very clear and useful. I'll stick on the irb variant but I like the ruby hack a lot. -- Posted via http://www.ruby-forum.com/.
From: Joel VanderWerf on 7 Jul 2008 01:32 Joel VanderWerf wrote: > If > you need to load files from a program, and keep their instance (not > local) variables, constants, and methods in separate scopes, you might > be interested in these: > > http://raa.ruby-lang.org/project/script/ Ok, I said no local variables, but it's possible to expose them to the caller too, using eval(var_name, binding). So anyway, the 0.3 release of the above lets you do the following: $ cat prog.rb require 'script' script = Script.load("my-script.rb") p eval("x", script.__script_scope) p script.__local_variable_get(:x) p script.__local_variables p script.instance_variables $ cat my-script.rb x = 4 require 'my-script-sub' $ cat my-script-sub.rb x = 5 y = 6 $ ruby prog.rb 4 4 ["__file__", "x"] ["@__script_scope", "@__loaded_features", "@__dir", "@__main_file"] -- vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
From: عمر ملقب بالثانی on 7 Jul 2008 16:06
Joel VanderWerf wrote: > Ok, I said no local variables, but it's possible to expose them to the > caller too, using eval(var_name, binding). Thanks again. Good to know this. -- Posted via http://www.ruby-forum.com/. |