What do you think about MAIN_BINDING for use it with eval():
eval("a = 'hello'",MAIN_BINDING)
puts a
outputs:
hello
?
What do you think about MAIN_BINDING for use it with eval():
eval("a = 'hello'",MAIN_BINDING)
puts a
outputs:
hello
?
Strictly speaking, there is no binding that would allow you to define new
variables in the main scope with the current semantics of #eval.
The issue (as I understand it), is that #eval opens up a new scope, sort of
like a block currently does, and variables don’t leak out of it. For example:
5.times do |i|
j = i
end
puts j
In Ruby 1.8 this fails because j isn’t defined (in Ruby 2.0, this won’t fail).
#eval is similar. It opens up a new scope that can only be accessed through
#eval, so you’d have to change the method itself. Strictly speaking, I guess
you could have a boolean argument that specifies whether #eval should use the
inner scope. That’d be more general.
Do I think it’s a good idea? I don’t know. I recall reading threads here
where that kind of thing was necessary for what the person wanted to do (like
in your example. You can’t define new variables in the general scope). I don’t
really know how common it is, though. On the other hand, I don’t know how much
you need to protect the main scope.
Perhaps #eval should be changed to let variables leak out of eval-scope, just
like they’ll leak out of blocks in the future.
On Wednesday 21 April 2004 7:09 am, Szymon Drejewicz wrote:
What do you think about MAIN_BINDING for use it with eval():
eval("a = 'hello'",MAIN_BINDING) puts a
outputs:
hello
Hi,
I’ve seen references to some TOP_LEVEL_BINDING in Google, I don’t know
if this is related.
I really feel strange about eval() not side effecting assignments
to new local variables. I guess the binding it uses is very special or
some logic is there to “undo” the creation of local variables. Weird.
For sure I don’t understand why this is happening in eval( stuff, binding).
If I provide a binding, I should have the option of whether is it rw or
rd_only.
But… I may be missing something.
Yours,
Jean-Hugues Robert
At 20:09 21/04/2004 +0900, you wrote:
What do you think about MAIN_BINDING for use it with eval():
eval("a = 'hello'",MAIN_BINDING) puts a
outputs:
hello?
Szymon Drejewicz drejewic@wsisiz.edu.pl writes:
What do you think about MAIN_BINDING for use it with eval():
eval("a = 'hello'",MAIN_BINDING) puts a
outputs:
hello?
Well, the following does work:
a = ‘goodbye’
eval(“a = ‘hello’”, binding())
puts a # => hello
The reason has to do with the differing manner in which ruby interprets
“puts a” in the presence and absence of a previous variable definition
for “a”.
If “a” is previously defined as a variable, the compiler causes the
“puts a” command to simply output its value; but if “a” is not
previously defined, my understanding is that “puts a” interprets “a” as
a method call. In this case, “eval” statement (whose command is not, of
course, touched by the interpreter) indeed sets the “a” variable in the
global scope, but the “print” statement doesn’t access it.
I’m don’t know if there’s a syntactical way around this.
–
Lloyd Zusman
ljz@asfast.com
The issue (as I understand it), is that #eval opens up a new scope
Well, not really. The problem is this is at *compile* time that ruby make
the difference between a variable and a method
When you write
eval("a = 'hello'",MAIN_BINDING)
puts a
ruby at compile time see a string and the statement
puts a
which is interpreted as
puts a() # method call because no local variable with the name `a'
# was defined
and you can't change this, just imagine
def tt(str)
eval(str)
puts a
end
tt("a = 'hello'")
tt("b = 'hello'")
ruby will not be able to see, that *latter* the method #tt will be called
with "a = 'hello'", and in this case `a' can be a local variable.
Just imagine that ruby read line from a file and then call the method #tt
with these lines.
Worst and perhaps I've forgotten to say it : eval is evil
Guy Decoux
If “a” is previously defined as a variable, the compiler causes the
“puts a” command to simply output its value; but if “a” is not
previously defined, my understanding is that “puts a” interprets “a” as
a method call. In this case, “eval” statement (whose command is not, of
course, touched by the interpreter) indeed sets the “a” variable in the
global scope, but the “print” statement doesn’t access it.
I think you meant “local scope”?
I’m don’t know if there’s a syntactical way around this.
There are ways, but they aren’t beautiful.
for example:
eval(“a = 4”)
puts a = a
=> 4
By the asignment ruby will treat a as a local variable
and give the right result.
OK eval is evil
You are right but if I can write
eval("$name='Alice'")
puts $name
and it’s OK, the same would be (hypothetically) with
eval("name='Alice'", MAIN_BINDING)
puts name
it just means “evaluate this command and execute it in main block…”
I know that is not so easy, but what’s wrong with that? Just want to write
self-writing code
But… OK, Ruby is enough strong language even without my MAIN_BINDING :-]
eval('proposal.reject')
Szymon Drejewicz
eval("name='Alice'", MAIN_BINDING)
puts name
Like have said matz the problem is with this
svg% cat b.rb
#!/usr/bin/ruby
def name
"a nice method with a nice name"
end
eval("name='Alice'")
puts name
svg%
svg% b.rb
a nice method with a nice name
svg%
because at compile time, the local variable `name' was not defined ruby
has compiled the script to make a call to the method #name
it just means "evaluate this command and execute it in main block..."
yes, this is what do ruby but it do it at *runtime* when
puts name
is interpreted at *compile* time.
This is at compile time, that ruby resolve `name' as
*) reference to a local variable (if it was previously found a variable
with this name)
*) *OR* a method call (if it don't exist a variable with this name)
and in your example at *compile* time the variable `name' don't exist
I know that is not so easy, but what's wrong with that? Just want to write
self-writing code
Don't make the error of a P language : an hash is really appropriate in
your case and it's perhaps the best solution
Guy Decoux