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:
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:
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