Eval question

I see. Thanks.

Is there anyway other way to create locals without explicitly
setting them?

val = nil
eval "val = 10"
puts val # -> 10

So val is created in a scope local to the eval invocation, unless it already exists in the nesting scope. I think :slight_smile:

Thomas

So val is created in a scope local to the eval invocation, unless it
already exists in the nesting scope. I think :slight_smile:

No, not really :slight_smile:

For example

pigeon% ruby -e 'eval "a = 12"; eval "p a"'
12
pigeon%

If the variable `a' is created in a scope local to the first #eval, then
this variable will no be accessible for the second #eval

puts val # -> 10

The problem is on this line. This is at *compile* time that ruby make the
difference between an access to a local variable or a method call,
i.e. ruby must make the choice between

  (1) : puts val # I try to access the local variable `val'
  (2) : puts val() # I call the method #val

this choice is made at compile time when ruby know *only* if it exist a
local variable and the rule is simple

  * if a variable 'val' was previously found then it make the choice (1)
  * otherwise it make the choice (2)

For example with

   eval "val = 12"
   p val

when it compile the second line, it has not yet executed the string for
#eval this mean that at this step it don't exist a local variable `val'
and ruby consider that it's a method call, i.e.

   eval "val = 12"
   p val()

At runtime
   * #eval will create a local variable `val'
   * *but* in the second line, ruby will try to call the method #val

Now when you write

   val = nil
   eval "val = 12"
   p val

when it compile the first line, it has found a new variable 'val'
when it compile the third line, it know that it exist a variable with the
name `val' and in this case it will create the node to access a local
variable.

At runtime, the 3 lines work with the same variable

p.s.: You'll have a similar problem with attribute writer

Guy Decoux

This is exactly the information I was looking for!

So even this works:

eval "val = 12"
val = val
p val

because at compile time the ‘val’ variable has been seen now.

I was just making sure that locals are only seen at compile-time, not
run-time and that there was no way of creating them at run-time (eval
compiles code).

···


Justin Johnson.

“ts” decoux@moulon.inra.fr wrote in message
news:200207241300.g6OD0wP13014@moulon.inra.fr

So val is created in a scope local to the eval invocation, unless it
already exists in the nesting scope. I think :slight_smile:

No, not really :slight_smile:

For example

pigeon% ruby -e 'eval “a = 12”; eval “p a”'
12
pigeon%

If the variable `a’ is created in a scope local to the first #eval, then
this variable will no be accessible for the second #eval

puts val # -> 10

The problem is on this line. This is at compile time that ruby make the
difference between an access to a local variable or a method call,
i.e. ruby must make the choice between

(1) : puts val # I try to access the local variable `val’
(2) : puts val() # I call the method #val

this choice is made at compile time when ruby know only if it exist a
local variable and the rule is simple

  • if a variable ‘val’ was previously found then it make the choice (1)
  • otherwise it make the choice (2)

For example with

eval "val = 12"
p val

when it compile the second line, it has not yet executed the string for
#eval this mean that at this step it don’t exist a local variable `val’
and ruby consider that it’s a method call, i.e.

eval "val = 12"
p val()

At runtime

  • #eval will create a local variable `val’
  • but in the second line, ruby will try to call the method #val

Now when you write

val = nil
eval "val = 12"
p val

when it compile the first line, it has found a new variable ‘val’
when it compile the third line, it know that it exist a variable with the
name `val’ and in this case it will create the node to access a local
variable.

At runtime, the 3 lines work with the same variable

p.s.: You’ll have a similar problem with attribute writer

Guy Decoux