Global_variable_set (like instance_variable_set)

Hello,

how can a function global_variable_set(gvarname, value) be
implemented? It should be similiar to the already existing method
Object#instance_variable_set, but set global variables rather than
instance variables.

Regards
Thomas

Thomas H. [email protected] wrote/schrieb
[email protected]:

how can a function global_variable_set(gvarname, value) be
implemented?

The function should behave like the following one, but not use
``eval’’ if possible.

def global_variable_set(gvarname, value)
eval(“#{gvarname.id2name}=value”)
end

Regards
Thomas

On 8/11/07, Thomas H. [email protected] wrote:

Hello,

how can a function global_variable_set(gvarname, value) be
implemented? It should be similiar to the already existing method
Object#instance_variable_set, but set global variables rather than
instance variables.

What problem do you need this for… it sounds like you could get by
with a different (and better) approach, but we’d need to know a little
more about what you’re trying to do.

What problem do you need this for… it sounds like you could get by
with a different (and better) approach, but we’d need to know a little
more about what you’re trying to do.

I believe for the record, a non-eval solution will be interesting to see
either way, even if he would use another (better) approach :slight_smile:

On Aug 11, 2007, at 23:29, Marc H. wrote:

What problem do you need this for… it sounds like you could get by
with a different (and better) approach, but we’d need to know a
little
more about what you’re trying to do.

I believe for the record, a non-eval solution will be interesting
to see
either way, even if he would use another (better) approach :slight_smile:

$ ruby
require ‘rubygems’
require ‘inline’

module Kernel
inline :C do |builder|
builder.include ‘“ruby.h”’

builder.c <<-‘EOF’
static VALUE
global_variable_set(char * varname, VALUE object) {
return rb_gv_set(varname, object);
}
EOF
end
end

p global_variable_set ‘foo’, 5
-:17: warning: parenthesize argument(s) for future version
p $foo

I hit ^D here

5D
5

“Gregory B.” [email protected] wrote/schrieb
[email protected]:

What problem do you need this for… it sounds like you could get by
with a different (and better) approach, but we’d need to know a little
more about what you’re trying to do.

Agreed that that there might be a better solution for the original
problem, but sometimes an intermediate problem becomes interesting per
se. Anyway, the original question is how to find a single, more
abstract function replacing these ones:

def with_output_to_string
$stdout, tmp = StringIO.new, $stdout
yield
$stdout, tmp = tmp, $stdout
tmp.rewind
tmp.read
end

def with_error_to_string
$stderr, tmp = StringIO.new, $stderr
yield
$stderr, tmp = tmp, $stderr
tmp.rewind
tmp.read
end

The only difference is $stdout vs. $stderr, so the idea was to pass
:$stdout resp. :$stderr as parameter.

Regards
Thomas

“Gregory B.” [email protected] wrote/schrieb
[email protected]:

Are you looking to do this to test a codebase that writes to $stdout
/ $stderr?

It’s rather about using someone else’s code. I’d prefer not to modify
it, because otherwise I had to merge every update.

def print_to_stdout
@out.puts “something”
end

def print_to_stderr
@err.puts “something”
end

Replacing puts'' by @out.puts’’ is such a modification of foreign
code that I’d like to avoid.

Regards
Thomas

On 8/12/07, Thomas H. [email protected] wrote:

“Gregory B.” [email protected] wrote/schrieb [email protected]:

Are you looking to do this to test a codebase that writes to $stdout
/ $stderr?

It’s rather about using someone else’s code. I’d prefer not to modify
it, because otherwise I had to merge every update.

Gotcha. IMO, there is no need for the abstraction if it’s limited to
these two functions.
You’re only talking about a couple lines of code, and your need for
this won’t expand much over time, it seems.

The helper is certainly useful though and I’d say if you wanted to use
eval to shorten it up, go for it, as long as it’s not exposed to user
input.

If you’ve got a C compiler, the ruby-inline solution is likely safer.

That having been said, you don’t want to create a Rube G. machine.
:slight_smile:

-greg

On 8/12/07, Thomas H. [email protected] wrote:

yield
$stderr, tmp = tmp, $stderr
tmp.rewind
tmp.read
end

The only difference is $stdout vs. $stderr, so the idea was to pass
:$stdout resp. :$stderr as parameter.

Interesting. Perhaps this is a direct translation of how you might do
this without an eval (untested):

module Kernel
def set_stdout(obj)
$stdout = obj
end

def set_stderr(obj)
$stderr = obj
end
end

def with_helper(msg)
temp = (msg == :stdout ? $stdout : $stderr)
send(“set_#{msg}”, StringIO.new)
yield
send(“set_#{msg}”,temp)
temp.rewind
temp.read
end

def with_output_to_string
with_helper(:stdout) { yield }
end

def with_error_to_string
with_helper(:stderr) { yield }
end

Of course, this doesn’t sound like a great idea, as unless the real
problem is actually a whole lot more interesting, this is just
unnecessary generalization and doesn’t clean things up any.

Are you looking to do this to test a codebase that writes to $stdout /
$stderr?

It’s perfectly reasonable to have a class or method definition like
this:

class Foo
def initialize(out=$stdout,err=$stderr)
@out = out
@err = err
end

def print_to_stdout
@out.puts “something”
end

def print_to_stderr
@err.puts “something”
end
end

Now if you wanted to test that, you could pass in your StringIO
objects. Maybe you can draw some ideas from that, if not, it’d be
interesting to see what you’re using this helper for.

On 8/12/07, Thomas H. [email protected] wrote:

“Gregory B.” [email protected] wrote/schrieb [email protected]:

Gotcha. IMO, there is no need for the abstraction if it’s limited to
these two functions.
You’re only talking about a couple lines of code, and your need for
this won’t expand much over time, it seems.

Nevertheless, if Ruby had explicit references (does it?), it would be
simple enough to have just one function instead of the original both
ones

You’ll want to catch up on this thread:
http://rubyurl.com/FrJ

Basically, variables in ruby are just containers for references to
objects. So you can’t change their bindings, which would be what
you’d need to do the kind of assignment you’ve shown there.

On 8/12/07, Gregory B. [email protected] wrote:

Basically, variables in ruby are just containers for references to
objects. So you can’t change their bindings, which would be what
you’d need to do the kind of assignment you’ve shown there.

Container is a bad word, sorry. Label might be better. A ruby
variable is a label for a reference, nothing more. (Please correct me
if I’m wrong, anyone).

“Gregory B.” [email protected] wrote/schrieb
[email protected]:

On 8/12/07, Thomas H. [email protected] wrote:

“Gregory B.” [email protected] wrote/schrieb [email protected]:

Nevertheless, if Ruby had explicit references (does it?), it would be
simple enough to have just one function instead of the original both
ones

You’ll want to catch up on this thread:
http://rubyurl.com/FrJ

This thread treats pass by reference'' which is like aliasing. With explicit references’’ I rather mean explicitly referencing (by
operator &'' in C resp. '’ in Perl) and dereferencing (by
operator *'' in C resp. $‘’ in Perl). Here’s a Perl example:

sub foo {
my ($ref) = @_; # consume argument array
${$ref}++; # dereference and increment
}
my $bar = 3;
foo($bar); # make a reference to $bar and pass it to the function
print $bar; # => 4

Regards
Thomas

“Gregory B.” [email protected] wrote/schrieb
[email protected]:

Gotcha. IMO, there is no need for the abstraction if it’s limited to
these two functions.
You’re only talking about a couple lines of code, and your need for
this won’t expand much over time, it seems.

Nevertheless, if Ruby had explicit references (does it?), it would be
simple enough to have just one function instead of the original both
ones, e.g. with ``()‘’ as a placeholder for a hypothetical
dereferencing operator:

def with_stream_to_string(stream)
()stream, tmp = StringIO.new, ()stream
yield
()stream, tmp = tmp, ()stream
tmp.rewind
tmp.read
end

Regards
Thomas

On Aug 12, 2007, at 14:20, Thomas H. wrote:

se. Anyway, the original question is how to find a single, more
def with_error_to_string
$stderr, tmp = StringIO.new, $stderr
yield
$stderr, tmp = tmp, $stderr
tmp.rewind
tmp.read
end

The only difference is $stdout vs. $stderr, so the idea was to pass
:$stdout resp. :$stderr as parameter.

Write one method that does both and returns both. Use only the one
you need. See #util_capture in lib/test/zentest_assertions.rb in
ZenTest.

On 8/13/07, Thomas H. [email protected] wrote:

http://rubyurl.com/FrJ
my $bar = 3;
foo($bar); # make a reference to $bar and pass it to the function
print $bar; # => 4

Sure, but it’s the same idea. You’re trying to change the binding of
$bar from a different scope

-greg