# Avoiding scope pitfall

**URL:** <https://www.ruby-forum.com/t/avoiding-scope-pitfall/91185>\
**Category:** Ruby\
**Created:** [April 5, 2007, 12:41pm UTC](https://www.ruby-forum.com/t/avoiding-scope-pitfall/91185 "2007-04-05T12:41:07Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![gga](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/b487fb/32.png) [@gga](https://www.ruby-forum.com/u/gga)\
**Post date:** [April 5, 2007, 12:41pm UTC](https://www.ruby-forum.com/t/avoiding-scope-pitfall/91185/1 "2007-04-05T12:41:07Z")

</div>

Here’s a simple snippet of code of a ruby scope pitfall (bug?) that I  
keep stumbling upon.  
Here a “global” function is invoked in two different contexts and  
returns different behavior due to self being set differently.

* * *

#!/usr/bin/env ruby

@x = ‘hello global’

def global\_func  
puts “global\_func: class:#{self.class} x=#@x”  
end

class A  
def test\_scope  
global\_func  
end  
end

global\_func

## a = A.new a.test\_scope

I’m wondering if this is intended behavior in the language. If  
intended, what’s the best approach to avoid running into this? I’m  
currently porting code from other languages with different (more  
correct to me) scoping, and this keeps tripping me.

---

<div class="post-metadata">

**Author:** ![gga](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/b487fb/32.png) [@gga](https://www.ruby-forum.com/u/gga)\
**Post date:** [April 5, 2007, 1:21pm UTC](https://www.ruby-forum.com/t/avoiding-scope-pitfall/91185/2 "2007-04-05T13:21:13Z")

</div>

On 05.04.2007 12:37, gga wrote:

> def global\_func
> 
> ## a = A.new a.test\_scope
> 
> I’m wondering if this is intended behavior in the language.

It is intended:

13:16:34 [Temp]: ./scope.rb  
#\<Method: Object#global\_func\>  
global\_func: class:Object x=hello global  
global\_func: class:A x=  
13:16:50 [Temp]: cat scope.rb  
#!/usr/bin/env ruby

@x = ‘hello global’

def global\_func  
puts “global\_func: class:#{self.class} x=#@x”  
end

p method( :global\_func )

class A  
def test\_scope  
global\_func  
end  
end

global\_func

a = A.new  
a.test\_scope  
13:16:53 [Temp]:

Every top level method is defined in class Object and thus inherited by  
all classes.

> If  
> intended, what’s the best approach to avoid running into this? I’m  
> currently porting code from other languages with different (more  
> correct to me) scoping, and this keeps tripping me.

Do not use instance variables in global _functions_. As simple as that.

Regards

robert

---

<div class="post-metadata">

**Author:** ![gga](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/b487fb/32.png) [@gga](https://www.ruby-forum.com/u/gga)\
**Post date:** [April 5, 2007, 1:35pm UTC](https://www.ruby-forum.com/t/avoiding-scope-pitfall/91185/3 "2007-04-05T13:35:27Z")

</div>

On Apr 5, 12:37 pm, “gga” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> def global\_func
> 
> a = A.new  
> a.test\_scope

I don’t know why you call that a pitfall. I tested the behaviour and  
it did exactly what I expected.

I think you are confused by what you call “global functions”. You’d  
better forget them: Ruby doesn’t have global functions. It only has  
methods. When you define a so-called “global function”, you’re just  
defining a method at the top level, which is in an object of class  
Oject, called main. Due to the scope rules at the top level, defining  
a method there adds it to the class Object, as an instance method.  
Nothing strange there so far.

Now when you define class A, it becomes automatically a subclass of  
Object, as you probably know, since Object is the root of the class  
hierarchy. As a subclass of Object, it gains all Object’s instance  
methods, including the one you just defined: “global\_func” (you can  
check that by running a.methods). So when you call “global\_func” in  
the test\_scope method, you are actually calling an inherited method,  
which will run then in the scope of the a object you created, _as one  
would expect from inherited methods_! So when you run a.test\_scope,  
global\_func will run in the scope of a, where self.class is A and @x  
hasn’t been assigned and thus returns nil. This is perfectly normal,  
given the rules of the Ruby language.

> * * *
> 
> I’m wondering if this is intended behavior in the language. If  
> intended, what’s the best approach to avoid running into this? I’m  
> currently porting code from other languages with different (more  
> correct to me) scoping, and this keeps tripping me.

Well, the answer is that yes, it is the intended behaviour in the  
language, in the sense that it is completely valid behaviour according  
to the rules of the language. Just forget about global functions: they  
are just methods of the class Object, which become available to all  
objects only due to inheritance, and thus follow _all_ the rules of  
inherited methods, included the rule that when called in an instance  
of a subclass, they run in the scope of that instance. Normally  
functions defined on the top level don’t care about this, as their  
behaviour normally does not depend on the state of the object they’re  
called in (like “puts”, which will output to $stdout anyway, since  
$stdout is a true global variable which refers to the same IO object  
everywhere). For others, we just don’t expect them to behave  
differently (no one would expect the “class” method to return anything  
but the class of the object they’re in).

A way to remember that behaviour might be to remember that methods  
defined on the top level act as if they had a “class Object … end”  
surrounding their definition. That might help you remember that they  
are inherited to other classes, rather than simply have a global  
scope.

And if you don’t want that behaviour, just have your top-level methods  
never rely on the scope they’re running in. That can be done for  
instance by only have them use global variables (but watch your thread  
safety go bye-bye if you write threaded code 🙂 ) and local variables  
(which are local to the scope of the method anyway, wherever that  
method’s used).

Hopefully with this you should understand why this behaviour is  
actually _correct_, when you think clearly about how the Ruby language  
works (i.e. it’s internally consistent). One thing I’ve noticed and  
liked about Ruby is how consistent it is, and how few exceptions and  
little rules you need to learn when you understand its basic  
principles. You just need to be consistent yourself in how you are  
applying those basic principles to your programs.

Cheers,

Christophe.
