# Nil? and non-existent objects

**URL:** <https://www.ruby-forum.com/t/nil-and-non-existent-objects/91116>\
**Category:** Ruby\
**Created:** [April 4, 2007, 9:25pm UTC](https://www.ruby-forum.com/t/nil-and-non-existent-objects/91116 "2007-04-04T21:25:15Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![zerohalo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/5fc32e/32.png) [@zerohalo](https://www.ruby-forum.com/u/zerohalo)\
**Post date:** [April 4, 2007, 9:25pm UTC](https://www.ruby-forum.com/t/nil-and-non-existent-objects/91116/1 "2007-04-04T21:25:15Z")

</div>

Why is it that the nil? method can sometimes be called on an object that  
doesn’t exist, and other times will return an error. Under what  
circumstances can you call the nil? method on a non-existent object?

Consider:

> > puts x = 1 if x.nil?  
> > =\> 1
> 
> > puts â€˜z is not definedâ€™ if z.nil?  
> > =\> NameError: undefined local variable or method â€˜zâ€™

Someone mentioned that = has higher precedence than if, so it could be  
that in the first statement x is assigned 1 before the conditional  
statement is run. However, x.nil? would then always return false.

---

<div class="post-metadata">

**Author:** ![zerohalo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/5fc32e/32.png) [@zerohalo](https://www.ruby-forum.com/u/zerohalo)\
**Post date:** [April 4, 2007, 9:46pm UTC](https://www.ruby-forum.com/t/nil-and-non-existent-objects/91116/2 "2007-04-04T21:46:11Z")

</div>

I think is because of the ruby’s analisis on the scope. That is, in:

puts x = 1 if x.nil?

ruby sees x in the scope even if it is never accesed nor asigned, but in

puts â€˜z is not definedâ€™ if z.nil?

z is never in scope, because it is present only inside a string, it does  
not appear anywhere before the call of the method “nil?”

you can do:

{ z } if z.nil? =\> returns nothing of nothings (not nil nor false) ruby  
don’t complain because z is seen in the scope

Also works:

“HELLO #{an\_unique\_var\_name}” if an\_unique\_var\_name.nil?

* * *

FranÃ§ois Montel wrote:

> Why is it that the nil? method can sometimes be called on an object that  
> doesn’t exist, and other times will return an error. Under what  
> circumstances can you call the nil? method on a non-existent object?
> 
> Consider:
> 
> > > puts x = 1 if x.nil?  
> > > =\> 1
> > 
> > > puts â€˜z is not definedâ€™ if z.nil?  
> > > =\> NameError: undefined local variable or method â€˜zâ€™
> 
> Someone mentioned that = has higher precedence than if, so it could be  
> that in the first statement x is assigned 1 before the conditional  
> statement is run. However, x.nil? would then always return false.

---

<div class="post-metadata">

**Author:** ![zerohalo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/5fc32e/32.png) [@zerohalo](https://www.ruby-forum.com/u/zerohalo)\
**Post date:** [April 4, 2007, 10:13pm UTC](https://www.ruby-forum.com/t/nil-and-non-existent-objects/91116/3 "2007-04-04T22:13:07Z")

</div>

On Thu, Apr 05, 2007 at 04:46:12AM +0900, Emmanuel O. wrote:

> I think is because of the ruby’s analisis on the scope. That is, in:
> 
> puts x = 1 if x.nil?
> 
> ruby sees x in the scope even if it is never accesed nor asigned, but in
> 
> puts ???z is not defined??? if z.nil?
> 
> z is never in scope, because it is present only inside a string, it does  
> not appear anywhere before the call of the method “nil?”

Is that a spec detail or an implementation detail? It might be nice to  
know whether, assuming a stable language specification, that operational  
characteristic might go away at some point.

---

<div class="post-metadata">

**Author:** ![zerohalo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/5fc32e/32.png) [@zerohalo](https://www.ruby-forum.com/u/zerohalo)\
**Post date:** [April 4, 2007, 9:57pm UTC](https://www.ruby-forum.com/t/nil-and-non-existent-objects/91116/4 "2007-04-04T21:57:05Z")

</div>

On Apr 4, 1:25 pm, “François Montel” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> =\> NameError: undefined local variable or method ‘z’  
> Consider this:

irb(main):001:0\> puts x=1 if x  
=\> nil

irb(main):002:0\> puts y if y=1  
(irb):2: warning: found = in conditional, should be ==  
NameError: undefined local variable or method `y’ for main:Object

irb(main):003:0\> if z=1 then puts z end  
(irb):3: warning: found = in conditional, should be ==  
1  
=\> nil

The difference between them is the order in which Ruby sees the  
assignment _when preparing_ (syntax parsing), not during execution.  
The ‘y’ and ‘z’ cases above should run the same way, but due to the  
way Ruby checks to determine if a variable exists, it needs to see an  
assignment earlier in the file than a reference to the value.

---

<div class="post-metadata">

**Author:** ![zerohalo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/5fc32e/32.png) [@zerohalo](https://www.ruby-forum.com/u/zerohalo)\
**Post date:** [April 4, 2007, 10:20pm UTC](https://www.ruby-forum.com/t/nil-and-non-existent-objects/91116/5 "2007-04-04T22:20:08Z")

</div>

On Apr 4, 2007, at 3:25 PM, François Montel wrote:

> Why is it that the nil? method can sometimes be called on an object  
> that  
> doesn’t exist, and other times will return an error. Under what  
> circumstances can you call the nil? method on a non-existent object?

It is an artifact of the way the Ruby parser works and the syntactical  
ambiguity of a method call with no arguments and local variables.

> Consider:
> 
> > > puts x = 1 if x.nil?  
> > > =\> 1

Here, the Ruby parser ‘sees’ the expression: ‘x = 1’ and concludes that  
x must be a local variable. It sees the expression and makes the  
determination about ‘x’ _before_ it sees the method call: ‘x.nil?’.  
Once it has made that determination is considers ‘x.nil?’ as a method  
call against the local variable ‘x’ and not as a method call for ‘x’  
relative to ‘self’.

The net effect is that the local variable ‘x’ is willed into existence  
by the parser (and defaults to nil). Since ‘x.nil?’  
evaluates to true, ‘puts x = 1’ is executed changing the value of x  
to 1, which gets printed.

Consider a situation where x was a method call with an argument:

puts x = 1 if x(‘foo’).nil?

In this case the parser sees no ambiguity, “x(‘foo’)” must be a method  
call even though it already saw ‘x = 1’ as a local variable assignment.

> > > puts ‘z is not defined’ if z.nil?  
> > > =\> NameError: undefined local variable or method ‘z’

Here the parser hasn’t seen ‘z’ until it comes across ‘z.nil?’. It  
makes the determination that z must be a method call. When the parsing  
is complete and the statement is executed, Ruby tries to call ‘z’ in  
the current context and finds that there really isn’t a method  
called ‘z’ and you get the Name Error.

Note that the _parser_ can’t determine if the method z exists or not.  
It is only at the time of execution that that can be determined:

def tricky  
def z; ‘z exists!’; end  
end

puts z rescue “z isn’t defined” # =\> “z isn’t defined”  
tricky  
puts z # =\> “z exists!”

Here is another example

if w # parser sees this as a method call, NameError  
# exception is raised.  
puts w = 42 # parser sees this as local variable assignment  
# but it never executes  
end

Now consider (in a new session of ruby or irb):

puts w = 42 if w # parser sees w as a local variable and initializes  
# w to nil, puts never executes

---

<div class="post-metadata">

**Author:** ![zerohalo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/5fc32e/32.png) [@zerohalo](https://www.ruby-forum.com/u/zerohalo)\
**Post date:** [April 4, 2007, 10:57pm UTC](https://www.ruby-forum.com/t/nil-and-non-existent-objects/91116/6 "2007-04-04T22:57:42Z")

</div>

Thanks, everyone, for the thorough explanation. This is all very  
helpful/educational.

---

<div class="post-metadata">

**Author:** ![zerohalo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/5fc32e/32.png) [@zerohalo](https://www.ruby-forum.com/u/zerohalo)\
**Post date:** [April 4, 2007, 11:32pm UTC](https://www.ruby-forum.com/t/nil-and-non-existent-objects/91116/7 "2007-04-04T23:32:15Z")

</div>

On Thu, Apr 05, 2007 at 04:25:23AM +0900, Fran?ois Montel wrote:

> Why is it that the nil? method can sometimes be called on an object that  
> doesn’t exist, and other times will return an error. Under what  
> circumstances can you call the nil? method on a non-existent object?
> 
> Consider:
> 
> > > puts x = 1 if x.nil?  
> > > =\> 1
> > 
> > > puts ???z is not defined??? if z.nil?  
> > > =\> NameError: undefined local variable or method ???z???

Maybe easier to understand if you consider this:

if false  
x = 0  
end

puts x.inspect # =\> nil

When the file is _parsed_, the assignment “x = 0” flags “x” as a  
local variable from that point onwards within the scope. This is true  
whether or not it is actually executed; it’s a parse-time decision as to  
whether “x” is a local variable or a method call with implicit receiver.

Regards,

Brian.

---

<div class="post-metadata">

**Author:** ![zerohalo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/5fc32e/32.png) [@zerohalo](https://www.ruby-forum.com/u/zerohalo)\
**Post date:** [April 4, 2007, 11:43pm UTC](https://www.ruby-forum.com/t/nil-and-non-existent-objects/91116/8 "2007-04-04T23:43:17Z")

</div>

[http://www.ruby-forum.com/topic/103712](http://www.ruby-forum.com/topic/103712)

You may want to look at this topic also 🙂

---

<div class="post-metadata">

**Author:** ![zerohalo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/5fc32e/32.png) [@zerohalo](https://www.ruby-forum.com/u/zerohalo)\
**Post date:** [April 4, 2007, 11:56pm UTC](https://www.ruby-forum.com/t/nil-and-non-existent-objects/91116/9 "2007-04-04T23:56:45Z")

</div>

FranÃ§ois Montel wrote:

> Why is it that the nil? method can sometimes be called on an object that  
> doesn’t exist, and other times will return an error. Under what  
> circumstances can you call the nil? method on a non-existent object?
> 
> Consider:
> 
> > > puts x = 1 if x.nil?  
> > > =\> 1
> > 
> > > puts â€˜z is not definedâ€™ if z.nil?  
> > > =\> NameError: undefined local variable or method â€˜zâ€™
> 
> Someone mentioned that = has higher precedence than if, so it could be  
> that in the first statement x is assigned 1 before the conditional  
> statement is run. However, x.nil? would then always return false.

You could also fix it this way 🙂

* * *

def x  
@x  
end

def x=(val)  
@x = val  
end

puts x=1 if x.nil?

* * *

This would output: 1

---

<div class="post-metadata">

**Author:** ![zerohalo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/5fc32e/32.png) [@zerohalo](https://www.ruby-forum.com/u/zerohalo)\
**Post date:** [April 5, 2007, 12:12am UTC](https://www.ruby-forum.com/t/nil-and-non-existent-objects/91116/10 "2007-04-05T00:12:16Z")

</div>

Jamal S. wrote:

> You could also fix it this way 🙂
> 
> * * *
> 
> def x  
> @x  
> end
> 
> def x=(val)  
> @x = val  
> end
> 
> puts x=1 if x.nil?
> 
> * * *
> 
> This would output: 1

Actually, it needs no fixing, or the def statements. The explanation  
(thanks, Brian, et al) is that “x=1 if x.nil?” works because when the  
parser sees ‘x=1’ it flags x as a local variable and creates it,  
assigning it the value nil. Only then does it execute x.nil?, which  
returns a value since x now exists.

In other words, if there is any reference to a new local variable in  
your code, even if that reference is not executed (as in Brian’s  
example), the local variable is created and assigned a nil value.

---

<div class="post-metadata">

**Author:** ![zerohalo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/5fc32e/32.png) [@zerohalo](https://www.ruby-forum.com/u/zerohalo)\
**Post date:** [April 5, 2007, 7:35am UTC](https://www.ruby-forum.com/t/nil-and-non-existent-objects/91116/11 "2007-04-05T07:35:01Z")

</div>

On Thu, Apr 05, 2007 at 06:56:46AM +0900, Jamal S. wrote:

> > =\> NameError: undefined local variable or method ???z???  
> > @x  
> > This would output: 1  
> > I think you should check your work before posting (I do)

Run this:

def x  
puts “calling main.x”  
@x  
end

def x=(val)  
puts “calling main.x=”  
@x = val  
end

puts x=1 if x.nil?

You’ll see that your two methods are never called, so they don’t make  
any  
difference.

---

<div class="post-metadata">

**Author:** ![zerohalo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/5fc32e/32.png) [@zerohalo](https://www.ruby-forum.com/u/zerohalo)\
**Post date:** [April 5, 2007, 11:22am UTC](https://www.ruby-forum.com/t/nil-and-non-existent-objects/91116/12 "2007-04-05T11:22:41Z")

</div>

Brian C. wrote:

> On Thu, Apr 05, 2007 at 06:56:46AM +0900, Jamal S. wrote:
> 
> > > =\> NameError: undefined local variable or method ???z???  
> > > @x  
> > > This would output: 1  
> > > I think you should check your work before posting (I do)

true, they are not?
