Binding - how to get current script?

I’d like to do something like this:

    eval("name = 'Alice')
    puts name

but I don’t know how to bind eval to current script “space” so I get the
error:

    test.rb:3: undefined local variable or method `name' for main
···


Szymon Drejewicz

Hi,

At Wed, 21 Apr 2004 18:44:12 +0900,
Szymon Drejewicz wrote in [ruby-talk:97808]:

but I don’t know how to bind eval to current script “space” so I get the
error:

    test.rb:3: undefined local variable or method `name' for main

A local variable created in eval is only visible in eval.

      eval("name = 'Alice'")
      puts eval("name")
···


Nobu Nakada

A local variable created in eval is only visible in eval.

:cry:

so there is no way to do something like:

    eval("name = 'Alice'", MAIN_BINDING)
    puts name

???

:-[

···


Szymon Drejewicz

A local variable created in eval is only visible in eval.

          eval("name = 'Alice'")
          puts eval("name")

Well, perhaps ruby can be changed to make it work like a P language

svg% cat a.pl
#!/usr/bin/perl -w
use strict;
{
    my $m;
    sub aa { eval '$m += 2' }
    sub bb { eval 'print "bb : $m\n"' }
    sub cc { $m += 3 }
    sub dd { print "dd : $m\n" }
}
for (0 .. 3) {
    aa(); bb();
    cc(); dd();
}
svg%

svg% ./perl -v a.pl

This is perl, v5.8.3 built for i686-linux

Copyright 1987-2003, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using `man perl' or `perldoc perl'. If you have access to the
Internet, point your browser at http://www.perl.com/, the Perl Home Page.

svg%

svg% ./perl a.pl
bb : 2
dd : 3
bb : 4
dd : 6
bb : 6
dd : 9
bb : 8
dd : 12
svg%

nice, no :-)))

Guy Decoux

I could write:

    eval("$name = 'Alice')
    puts $name

but it is not smart solution. Exactly what I want to do is:

    pgResult.fields.each_with_index do |fieldName,i| 
        eval(%Q[ #{fieldName} = '#{pgResult.result[0][i]}' ]) 
    end

alternative code

    fname, sname, age, height, sex = pgResult.result.flatten

but if my table in DB has 30 fields the line above isn’t so nice so this is
the reason why I decided to use eval() for this dirty work :slight_smile:

···


Szymon Drejewicz

Hi,

At Wed, 21 Apr 2004 19:24:05 +0900,
Szymon Drejewicz wrote in [ruby-talk:97815]:

A local variable created in eval is only visible in eval.

:cry:

so there is no way to do something like:

    eval("name = 'Alice'", MAIN_BINDING)
    puts name

name = nil
eval(“name = ‘Alice’”)
puts name

You can change existing variables, but cannot add new
variables.

Perhaps, you are looking for wrong way, I guess.

···


Nobu Nakada

        pgResult.fields.each_with_index do |fieldName,i|
            eval(%Q[ #{fieldName} = '#{pgResult.result[0][i]}' ])
        end

use an hash

        hash = {}
        pgResult.fields.each_with_index do |fieldName,i|
            hash[fieldName] = pgResult.result[0][i]
        end

or something like this

eval is *evil*

Guy Decoux

There is :slight_smile:
You can use Kernel#binding to get the current binding,
and pass it to eval:

irb(main):001:0> eval(“name = ‘Alice’”, binding())
=> “Alice”
irb(main):002:0> name
=> “Alice”

···

On Wed, 21 Apr 2004 12:18:18 +0200, Szymon Drejewicz wrote:

A local variable created in eval is only visible in eval.

:cry:

so there is no way to do something like:

    eval("name = 'Alice'", MAIN_BINDING)
    puts name

name = nil
eval(“name = ‘Alice’”)
puts name

You can change existing variables, but cannot add new
variables.

It’s nice to know that eval() works in this way. Maybe in the future I’ll
use it for change variable value but this time I have to change every 30
local variables to global variables.

If I need (and can) to write:

    name = nil
    sname = nil
    age = nil
    eval("name = 'Alice'")
    eval("sname = 'Smith'")
    eval("age = '19'")

better is to write just:

    name = 'Alice'
    sname = 'Smith'
    age = '19'

but the problem is I don’t know the names of that variables for now, so I
need to make them parameters:

    names = someArrayWithVariableNamesProducer
    values = someArrayWithVariableValuesProducer
    names.each_with_index { |varName,i| 
        eval("#{varName} = #{values[i]}", MAIN_BINDING) 
    }  

So I think it is candidate for Ruby-Proposal :slight_smile: to make a additional
binding named i.e. “MAIN_BINDING” wich points current script…

:slight_smile:

···


Szymon Drejewicz

I think the solution with Hash is the best for now… thank you.

···


Szymon Drejewicz

Kristof Bastiaensen wrote:

There is :slight_smile:

no, unfortunately it works that way only in IRB not in Ruby script.

:-]

···


Szymon Drejewicz

However this bombs: eval(“name = ‘Alice’”, binding); puts name
This is probably because the reference to name is compiled before
eval() is called. Basically: the local variable is created but
the compiled code does not bind to it.

Try this:
def test()
eval( “a = ‘titi’”, binding)
puts “Compiled: #{a}”
rescue
eval( ‘puts “Dynamic: #{a}”’)
end
test()

Jean-Hugues

···

At 21:09 21/04/2004 +0900, you wrote:

On Wed, 21 Apr 2004 12:18:18 +0200, Szymon Drejewicz wrote:

A local variable created in eval is only visible in eval.

:cry:

so there is no way to do something like:

    eval("name = 'Alice'", MAIN_BINDING)
    puts name

There is :slight_smile:
You can use Kernel#binding to get the current binding,
and pass it to eval:

irb(main):001:0> eval(“name = ‘Alice’”, binding())
=> “Alice”
irb(main):002:0> name
=> “Alice”


Web: @jhr is virteal, virtually real
Phone: +33 (0) 4 92 27 74 17

Try it in a program instead of in irb. That fails.

enigodev % cat t.rb
#!/usr/bin/ruby

eval(‘name = “alice”’,binding)
puts name
enigodev % ./t.rb
./t.rb:4: undefined local variable or method `name’ for main:Object
(NameError)
enigodev %

If one replaces name with @name, then it works. There is probably a
logical explanation for why local variables behave in this way within an
eval, but I do find it surprising, coming from Perl.

Kirk Haines

···

On Wed, 21 Apr 2004, Kristof Bastiaensen wrote:

There is :slight_smile:
You can use Kernel#binding to get the current binding,
and pass it to eval:

irb(main):001:0> eval(“name = ‘Alice’”, binding())
=> “Alice”
irb(main):002:0> name
=> “Alice”

Oh… That’s strange! So eval creates a new binding for new local
variables, instead of the given binding. I wonder if that is the intended
behaviour… Maybe it could be a solution to declare the variables that
you need:

fname, sname, age = nil

<code using fname, sname, age>

The variables that you don’t need will be inside eval,
but you don’t need them anyway.

···

On Wed, 21 Apr 2004 14:13:32 +0200, Szymon Drejewicz wrote:

Kristof Bastiaensen wrote:

There is :slight_smile:

no, unfortunately it works that way only in IRB not in Ruby script.

:-]

“Szymon Drejewicz” drejewic@wsisiz.edu.pl schrieb im Newsbeitrag
news:c65k9g$bc3$1@portraits.wsisiz.edu.pl…

name = nil
eval(“name = ‘Alice’”)
puts name

You can change existing variables, but cannot add new
variables.

It’s nice to know that eval() works in this way. Maybe in the future
I’ll
use it for change variable value but this time I have to change every 30
local variables to global variables.

If I need (and can) to write:

    name = nil
    sname = nil
    age = nil
    eval("name = 'Alice'")
    eval("sname = 'Smith'")
    eval("age = '19'")

better is to write just:

    name = 'Alice'
    sname = 'Smith'
    age = '19'

but the problem is I don’t know the names of that variables for now, so
I
need to make them parameters:

    names = someArrayWithVariableNamesProducer
    values = someArrayWithVariableValuesProducer
    names.each_with_index { |varName,i|
        eval("#{varName} = #{values[i]}", MAIN_BINDING)
    }

So I think it is candidate for Ruby-Proposal :slight_smile: to make a additional
binding named i.e. “MAIN_BINDING” wich points current script…

  1. The main binding is available already, 2. your proposal won’t help
    since evat still is cannot create variables in that binding that you can
    access in code, 3. even if eval could do that how would you want to use
    that? I mean, you have to know var names to use them directly so what do
    you gain by eval. OTOH, if you have those names only in some kind of
    collection (array, etc.) then you can as well use a hash to store them.
    IMHO you are looking for the wrong solution.

Maybe you should rather use a Hash instead of variables.

OpenStruct is another option that comes to mind:

16:36:35 [ruby]: ruby os.rb



16:36:39 [ruby]: cat os.rb
require ‘ostruct’

str = OpenStruct.new
p str
str.name = ‘foo’
p str
str.bar = ‘hello’
p str
16:36:51 [ruby]:

Kind regards

robert

Hi,

···

In message “Re: binding - how to get current script?” on 04/04/21, Kirk Haines khaines@enigo.com writes:

If one replaces name with @name, then it works. There is probably a
logical explanation for why local variables behave in this way within an
eval, but I do find it surprising, coming from Perl.

Local variable determination is done in compile time, so that eval
(which is done in run time) cannot affect the determination. It’s
just too late. But “irb” does compile and execute line by line.
That’s the reason eval works for irb (i.e. eval is executed before
compiling the next line).

						matz.

Yukihiro Matsumoto wrote:

Hi,

If one replaces name with @name, then it works. There is probably a
logical explanation for why local variables behave in this way within an
eval, but I do find it surprising, coming from Perl.

Local variable determination is done in compile time, so that eval
(which is done in run time) cannot affect the determination. It’s
just too late. But “irb” does compile and execute line by line.
That’s the reason eval works for irb (i.e. eval is executed before
compiling the next line).

  					matz.

Why is there this difference between compile time and runtime? I had
assumed compile time was just a big eval call? Also, what happens when
you eval inside an eval is that a seperate scope or the same?

Charles Comstock

···

In message “Re: binding - how to get current script?” > on 04/04/21, Kirk Haines khaines@enigo.com writes:

Hi,

···

In message “Re: binding - how to get current script?” on 04/04/22, Charles Comstock cc1@cec.wustl.edu writes:

Why is there this difference between compile time and runtime? I had
assumed compile time was just a big eval call? Also, what happens when
you eval inside an eval is that a seperate scope or the same?

eval does compile given string, then run compiled internal AST. Same
compile-time/run-time principle is applied in eval too.

						matz.