# Global\_variable\_set (like instance\_variable\_set)

**URL:** <https://www.ruby-forum.com/t/global-variable-set-like-instance-variable-set/111820>\
**Category:** Ruby\
**Created:** [August 11, 2007, 5:42pm UTC](https://www.ruby-forum.com/t/global-variable-set-like-instance-variable-set/111820 "2007-08-11T17:42:05Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![samoht](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ac8455/32.png) [@samoht](https://www.ruby-forum.com/u/samoht)\
**Post date:** [August 11, 2007, 5:42pm UTC](https://www.ruby-forum.com/t/global-variable-set-like-instance-variable-set/111820/1 "2007-08-11T17:42:05Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![samoht](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ac8455/32.png) [@samoht](https://www.ruby-forum.com/u/samoht)\
**Post date:** [August 11, 2007, 6:11pm UTC](https://www.ruby-forum.com/t/global-variable-set-like-instance-variable-set/111820/2 "2007-08-11T18:11:08Z")

</div>

Thomas H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote/schrieb  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> 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

---

<div class="post-metadata">

**Author:** ![samoht](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ac8455/32.png) [@samoht](https://www.ruby-forum.com/u/samoht)\
**Post date:** [August 11, 2007, 7:36pm UTC](https://www.ruby-forum.com/t/global-variable-set-like-instance-variable-set/111820/3 "2007-08-11T19:36:16Z")

</div>

On 8/11/07, Thomas H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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.

---

<div class="post-metadata">

**Author:** ![samoht](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ac8455/32.png) [@samoht](https://www.ruby-forum.com/u/samoht)\
**Post date:** [August 12, 2007, 8:29am UTC](https://www.ruby-forum.com/t/global-variable-set-like-instance-variable-set/111820/4 "2007-08-12T08:29:11Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![samoht](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ac8455/32.png) [@samoht](https://www.ruby-forum.com/u/samoht)\
**Post date:** [August 12, 2007, 11:08am UTC](https://www.ruby-forum.com/t/global-variable-set-like-instance-variable-set/111820/5 "2007-08-12T11:08:21Z")

</div>

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 🙂

$ 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

---

<div class="post-metadata">

**Author:** ![samoht](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ac8455/32.png) [@samoht](https://www.ruby-forum.com/u/samoht)\
**Post date:** [August 12, 2007, 11:20pm UTC](https://www.ruby-forum.com/t/global-variable-set-like-instance-variable-set/111820/6 "2007-08-12T23:20:36Z")

</div>

“Gregory B.” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote/schrieb  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> 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

---

<div class="post-metadata">

**Author:** ![samoht](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ac8455/32.png) [@samoht](https://www.ruby-forum.com/u/samoht)\
**Post date:** [August 13, 2007, 12:20am UTC](https://www.ruby-forum.com/t/global-variable-set-like-instance-variable-set/111820/7 "2007-08-13T00:20:42Z")

</div>

“Gregory B.” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote/schrieb  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> 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

---

<div class="post-metadata">

**Author:** ![samoht](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ac8455/32.png) [@samoht](https://www.ruby-forum.com/u/samoht)\
**Post date:** [August 13, 2007, 12:27am UTC](https://www.ruby-forum.com/t/global-variable-set-like-instance-variable-set/111820/8 "2007-08-13T00:27:43Z")

</div>

On 8/12/07, Thomas H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> “Gregory B.” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote/schrieb [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):
> 
> > 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.  
🙂

-greg

---

<div class="post-metadata">

**Author:** ![samoht](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ac8455/32.png) [@samoht](https://www.ruby-forum.com/u/samoht)\
**Post date:** [August 12, 2007, 11:40pm UTC](https://www.ruby-forum.com/t/global-variable-set-like-instance-variable-set/111820/9 "2007-08-12T23:40:37Z")

</div>

On 8/12/07, Thomas H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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.

---

<div class="post-metadata">

**Author:** ![samoht](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ac8455/32.png) [@samoht](https://www.ruby-forum.com/u/samoht)\
**Post date:** [August 13, 2007, 2:16am UTC](https://www.ruby-forum.com/t/global-variable-set-like-instance-variable-set/111820/10 "2007-08-13T02:16:49Z")

</div>

On 8/12/07, Thomas H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> “Gregory B.” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote/schrieb [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):
> 
> > 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](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.

---

<div class="post-metadata">

**Author:** ![samoht](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ac8455/32.png) [@samoht](https://www.ruby-forum.com/u/samoht)\
**Post date:** [August 13, 2007, 2:19am UTC](https://www.ruby-forum.com/t/global-variable-set-like-instance-variable-set/111820/11 "2007-08-13T02:19:50Z")

</div>

On 8/12/07, Gregory B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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).

---

<div class="post-metadata">

**Author:** ![samoht](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ac8455/32.png) [@samoht](https://www.ruby-forum.com/u/samoht)\
**Post date:** [August 13, 2007, 11:11am UTC](https://www.ruby-forum.com/t/global-variable-set-like-instance-variable-set/111820/12 "2007-08-13T11:11:25Z")

</div>

“Gregory B.” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote/schrieb  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> On 8/12/07, Thomas H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > “Gregory B.” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote/schrieb [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):
> > 
> > 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](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

---

<div class="post-metadata">

**Author:** ![samoht](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ac8455/32.png) [@samoht](https://www.ruby-forum.com/u/samoht)\
**Post date:** [August 13, 2007, 1:22am UTC](https://www.ruby-forum.com/t/global-variable-set-like-instance-variable-set/111820/13 "2007-08-13T01:22:47Z")

</div>

“Gregory B.” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote/schrieb  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> 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

---

<div class="post-metadata">

**Author:** ![samoht](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ac8455/32.png) [@samoht](https://www.ruby-forum.com/u/samoht)\
**Post date:** [August 13, 2007, 10:54pm UTC](https://www.ruby-forum.com/t/global-variable-set-like-instance-variable-set/111820/14 "2007-08-13T22:54:09Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![samoht](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ac8455/32.png) [@samoht](https://www.ruby-forum.com/u/samoht)\
**Post date:** [August 13, 2007, 5:08pm UTC](https://www.ruby-forum.com/t/global-variable-set-like-instance-variable-set/111820/15 "2007-08-13T17:08:25Z")

</div>

On 8/13/07, Thomas H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > [http://rubyurl.com/FrJ](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
