Accessing variables when loading a file to irb

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

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/

Thanks a lot. Very clear and useful.

I’ll stick on the irb variant but I like the ruby hack a lot.

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.

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”]