binding - how to get current script?

S

Szymon Drejewicz

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
 
N

nobu.nokada

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

Szymon Drejewicz

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

:'-(

so there is no way to do something like:

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

???

:-[
 
T

ts

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

n> eval("name = 'Alice'")
n> 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
 
N

nobu.nokada

Hi,

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

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

Szymon Drejewicz

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]}' ])
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 :)
 
T

ts

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

use an hash

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

or something like this

eval is *evil*



Guy Decoux
 
S

Szymon Drejewicz

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}", MAIN_BINDING)
}

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

:)
 
K

Kristof Bastiaensen

:'-(

so there is no way to do something like:

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

There is :)
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"
 
K

Kristof Bastiaensen

Kristof said:

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

:-]

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
<your code with eval>
<code using fname, sname, age>

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

Jean-Hugues ROBERT

There is :)
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"

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
 
R

Robert Klemme

Szymon Drejewicz said:
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}", MAIN_BINDING)
}

So I think it is candidate for Ruby-Proposal :) 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
<OpenStruct>
<OpenStruct name="foo">
<OpenStruct name="foo" bar="hello">
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
 

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