# Question on if / defined?()

**URL:** <https://www.ruby-forum.com/t/question-on-if-defined/193438>\
**Category:** Ruby\
**Created:** [August 17, 2010, 6:05pm UTC](https://www.ruby-forum.com/t/question-on-if-defined/193438 "2010-08-17T18:05:51Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jedrin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/47e85d/32.png) [@Jedrin](https://www.ruby-forum.com/u/Jedrin)\
**Post date:** [August 17, 2010, 6:05pm UTC](https://www.ruby-forum.com/t/question-on-if-defined/193438/1 "2010-08-17T18:05:51Z")

</div>

assuming x is not defined, why does the statement

x = true if !defined?(x)

produce x is nil ?

y = true if !defined?(x)

is no different

this however works fine:

if !defined?(x)  
x = true  
end

---

<div class="post-metadata">

**Author:** ![Jedrin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/47e85d/32.png) [@Jedrin](https://www.ruby-forum.com/u/Jedrin)\
**Post date:** [August 17, 2010, 6:21pm UTC](https://www.ruby-forum.com/t/question-on-if-defined/193438/2 "2010-08-17T18:21:39Z")

</div>

On Tue, Aug 17, 2010 at 12:05 PM, Jedrin [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> assuming x is not defined, why does the statement
> 
> x = true if !defined?(x)
> 
> produce x is nil ?

Because x is defined, this happens at parse time so it doesn’t matter  
if the assignment is executed or not.

> y = true if !defined?(x)
> 
> is no different

Not by itself

y = true if !defined? x

y # =\> true

I’m guessing you had this in a program AFTER something which defined x

> this however works fine:
> 
> if !defined?(x)  
> because at this point x is NOT defined since the parser hasn’t yet seen  
> it.  
> x = true  
> end

HTH

–  
Rick DeNatale

Blog: [http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)  
Github: [rubyredrick (Rick DeNatale) · GitHub](http://github.com/rubyredrick)  
Twitter: @RickDeNatale  
WWR: [http://www.workingwithrails.com/person/9021-rick-denatale](http://www.workingwithrails.com/person/9021-rick-denatale)  
LinkedIn: [http://www.linkedin.com/in/rickdenatale](http://www.linkedin.com/in/rickdenatale)

---

<div class="post-metadata">

**Author:** ![Jedrin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/47e85d/32.png) [@Jedrin](https://www.ruby-forum.com/u/Jedrin)\
**Post date:** [August 17, 2010, 7:14pm UTC](https://www.ruby-forum.com/t/question-on-if-defined/193438/3 "2010-08-17T19:14:01Z")

</div>

Rick Denatale wrote:

> I’m guessing you had this in a program AFTER something which defined x

The two statements were probably typed sequentioally. Consider the  
outputs of two different irb sessions:

irb(main):001:0\> y = true if !defined?(x)  
=\> true  
irb(main):002:0\> y  
=\> true  
irb(main):003:0\>

and

irb(main):001:0\> x = true if !defined?(x)  
=\> nil  
irb(main):002:0\> x  
=\> nil  
irb(main):003:0\> y = true if !defined?(x)  
=\> nil  
irb(main):004:0\> y  
=\> nil  
irb(main):005:0\> x  
=\> nil  
irb(main):006:0\>

x was defined as nil.

js

---

<div class="post-metadata">

**Author:** ![Jedrin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/47e85d/32.png) [@Jedrin](https://www.ruby-forum.com/u/Jedrin)\
**Post date:** [August 17, 2010, 7:30pm UTC](https://www.ruby-forum.com/t/question-on-if-defined/193438/4 "2010-08-17T19:30:20Z")

</div>

Rick Denatale wrote:

> Because x is defined, this happens at parse time so it doesn’t matter  
> if the assignment is executed or not.

Is this because when the parser sees ‘x = …’, Ruby automatically  
assigns a reference to the variable x?

It seems to me that this is the only way that this behavior makes sense.

js

---

<div class="post-metadata">

**Author:** ![Jedrin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/47e85d/32.png) [@Jedrin](https://www.ruby-forum.com/u/Jedrin)\
**Post date:** [August 17, 2010, 11:23pm UTC](https://www.ruby-forum.com/t/question-on-if-defined/193438/5 "2010-08-17T23:23:52Z")

</div>

On Tue, Aug 17, 2010 at 6:30 PM, John S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> Rick Denatale wrote:
> 
> > Because x is defined, this happens at parse time so it doesn’t matter  
> > if the assignment is executed or not.
> 
> Is this because when the parser sees ‘x = …’, Ruby automatically  
> assigns a reference to the variable x?

I think that’s correct, but I’d welcome confirmation from those more  
knowledgeable about this.

irb  
x  
#=\> NameError: undefined local variable or method ‘x’ for main:Object  
x = x  
#=\> nil

Sort of assigning itself by it’s own bootstraps?

---

<div class="post-metadata">

**Author:** ![Jedrin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/47e85d/32.png) [@Jedrin](https://www.ruby-forum.com/u/Jedrin)\
**Post date:** [August 18, 2010, 11:36am UTC](https://www.ruby-forum.com/t/question-on-if-defined/193438/6 "2010-08-18T11:36:29Z")

</div>

Here’s a simpler example:

if false  
x = 123  
end  
puts x # nil

x is defined, and has value nil. What has happened?

When the code is _parsed_ (before it is executed at all, just when Ruby  
is building an in-memory representation of the program), if Ruby sees an  
assignment like x = … then it marks x as being a local variable,  
reserving a slot for it on the stack.

Whether the assignment is actually executed later or not is irrelevant.  
From this point onwards to the end of the current scope, x is defined,  
and is a local variable.

Why does ruby do this? There is a local variable / method call  
ambiguity. Because you don’t declare variables in Ruby, and because a  
method call doesn’t need parentheses after it, a bare “x” could be  
either retrieving the value of x, or it could be calling the method x  
with no arguments.

This simple parse-time algorithm decides in advance which you meant,  
without you having to declare it.

```
puts x # undefined local variable or method `x'

def x
  "Method x"
end
puts x # Method x

x = 123
puts x # 123

```

At this point it’s decided that ‘x’ is a local variable, although you  
can still force a method call instead:

```
puts x # 123
puts self.x # Method x
puts x() # Method x
```

---

<div class="post-metadata">

**Author:** ![Jedrin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/47e85d/32.png) [@Jedrin](https://www.ruby-forum.com/u/Jedrin)\
**Post date:** [August 18, 2010, 2:21am UTC](https://www.ruby-forum.com/t/question-on-if-defined/193438/7 "2010-08-18T02:21:51Z")

</div>

Shy of looking at the code:  
The following appears that when using the ternary operator it sheds a  
little  
light on the state of x.state, in our case true or false.

In the first case x is assigned to true or false. Its forced into a  
state.  
Now we follow up with y returning false, also. In either case, we set  
the  
receiver (lvalue) to a known

! irb  
ruby-1.9.2-preview3 \> x = !defined?(x) ? true : false  
=\> false  
ruby-1.9.2-preview3 \> x  
=\> false  
ruby-1.9.2-preview3 \> y = !defined?(x) ? true : false  
=\> false  
ruby-1.9.2-preview3 \> y  
=\> false

When we go into the assignment x=true the if statement will execute and  
upon  
its success will store true into the x variable. I am suggesting this x  
variable must be instantiated as the line is digested by the compiler  
and  
therefore is instantiated as x with no assignment. Hence, we have one  
state  
true and the opposite is no state or nil

The result this statement finds it if false nil (no state) is reported  
(returned) as the if has failed to fire and invoke the intended  
statement…  
No statement, nil.

ruby-1.9.2-preview3 \> x = true if !defined?(x)  
=\> nil

However, x is untouched and is still set to false, below.

ruby-1.9.2-preview3 \> x  
=\> false

ruby-1.9.2-preview3 \> l = true if !defined?(x)  
=\> nil  
ruby-1.9.2-preview3 \> l  
=\> false  
ruby-1.9.2-preview3 \>

The result below seems to follow this thinking: If is fired and  
assignment  
is invoked and x than is assigned true.

ruby-1.9.2-preview3 \> x = true if defined?(x)  
=\> true  
ruby-1.9.2-preview3 \> x  
=\> true  
ruby-1.9.2-preview3 \>

So, the statement on the left of an if Statement must be parsed and  
instantiated for the compiler to have something to invoke on the if  
statement being successful.

I would think this is a compiler decision of optimistic logic. The  
reverse  
of this cold be the firing than instantiates the statement to be invoked  
which would be pessimistic and seems to be open up a rabbit hole that  
may  
pose a problematic recovery.
