Ruby proposal: MAIN_BINDING

S

Szymon Drejewicz

What do you think about MAIN_BINDING for use it with eval():

eval("a = 'hello'",MAIN_BINDING)
puts a

outputs:
hello


?
 
D

Dan Doel

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.

- Dan
 
T

ts

D> 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
 
J

Jean-Hugues ROBERT

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
 
L

Lloyd Zusman

Szymon Drejewicz said:
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.
 
S

Szymon Drejewicz

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')
 
T

ts

S> eval("name='Alice'", MAIN_BINDING)
S> 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

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

S> I know that is not so easy, but what's wrong with that? Just want to write
S> 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
 
K

Kristof Bastiaensen

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.
 

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
474,145
Messages
2,570,825
Members
47,371
Latest member
Brkaa

Latest Threads

Top