Accessing variables when loading a file to irb

I

Ib Lis

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 :
#<Set: {:booktitle, :volume, :pages, :issn, :note, :ps, :number,
:author, :custom, :year, :title, :journal}>
=> trueNameError: undefined local variable or method `fields' for main:Object

Thanks in advance for any hints
 
J

Joel VanderWerf

Ib said:
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.
 
J

Joel VanderWerf

Joel said:
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"]
 
Ø

عمر ملقب بالثانی

Joel said:
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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top