Undefineds and or-equals

So, we all know that this works:

foo ||= nil
puts "blah" if foo # => nil

but prior to that point, foo has not been defined.

If instead of the or-equals first, one tries:

puts "blah" if foo

one gets a NameError exception.

What is the actual mechanism in Ruby that allows the first form where
foo has not yet been defined? I know it works, I’m trying to understand
why the first form does not also raise the NameError? Ruby magic? (This
is just idle curiosity, I’m not really sweating over this!)

On 10/23/2013 11:34 AM, Tamara T. wrote:

one gets a NameError exception.

What is the actual mechanism in Ruby that allows the first form where foo has
not yet been defined? I know it works, I’m trying to understand why the first form
does not also raise the NameError? Ruby magic? (This is just idle curiosity, I’m
not really sweating over this!)

I’m not really sure if I know what you’re asking but I can give it a
shot.

The mechanism that allows this particular paradigm in Ruby is the ||=
operator itself. Many have waxed poetic about it [1] but the basic gist
is that ||= acts very similarly to:

foo || foo = nil

I say “very similarly” because you could try to run the above code and
it would throw a NameError. When the ‘shorthand’ of that expression
(||=) is encountered the parser executes some Ruby Magic™ and creates
the foo variable in a way that doesn’t throw an error. The example [1]
uses is helpful here. If you run this:

x = 1 if 2 == 5
puts x

Ruby will output ‘nil’ instead of throwing a NameError. The assignment
(even if it’s never directly evaluated) causes the parser to create x in
such a way that it’s usable later on. Same thing with ||=.

Does that answer your question? You may be asking something else here.

[1]
http://www.rubyinside.com/what-rubys-double-pipe-or-equals-really-does-5488.html

On Oct 23, 2013, at 12:55 PM, Corin S. [email protected]
wrote:

puts "blah" if foo

[1]
What Ruby’s ||= (Double Pipe / Or Equals) Really Does

I am familiar with that “very similar” thing. It’s the Ruby Magic []
thing I more wondering about. The example you gave is also interesting.
This isn’t a really serious enquiry, I was just wondering how Ruby makes
the determination about what’s defined when and how in these situations.
On the occasions where I see that NameError thrown, it’s pretty obvious
what I (haven’t) done.

From: ruby-talk [mailto:[email protected]] On Behalf Of Corin
Schedler

The mechanism that allows this particular paradigm in Ruby is the ||=
operator itself. Many have waxed poetic about it [1] but the basic gist
is that ||= acts very similarly to:

foo || foo = nil

I thought this was more like:

foo = foo || nil

Jamal Wills

On Thu, Oct 24, 2013 at 8:06 AM, Tamara T. [email protected]
wrote:

I am familiar with that “very similar” thing. It’s the Ruby Magic [] thing I
more wondering about. The example you gave is also interesting. This isn’t a
really serious enquiry, I was just wondering how Ruby makes the determination
about what’s defined when and how in these situations.

The Ruby parser determines local variables when it finds a symbol a a
LHS of an assigment expression. From that point on, any reference to
that symbol are treated as local variables. In the case of the ||=,
here you have the magic that tells that this is an assignment
expression:

https://github.com/ruby/ruby/blob/trunk/parse.y#L7404

  case '|':
    if ((c = nextc()) == '|') {
        lex_state = EXPR_BEG;
        if ((c = nextc()) == '=') {
            set_yylval_id(tOROP);
            lex_state = EXPR_BEG;
            return tOP_ASGN;
        }

When it finds ||=, that’s an assignment expression, so the LHS is
considered a local variable.

Jesus.

On Thu, Oct 24, 2013 at 5:08 AM, Jesús Gabriel y Galán
[email protected] wrote:

When it finds ||=, that’s an assignment expression, so the LHS is
considered a local variable.

Jesus.

Awesome explanation. Thank you, Jesus.

On Thu, Oct 24, 2013 at 2:52 PM, WILLS, JAMAL A [email protected] wrote:

    foo = foo || nil

Jamal Wills

If you read the article posted above by Corin:
http://www.rubyinside.com/what-rubys-double-pipe-or-equals-really-does-5488.html
you will see the full explanation. The difference is more apparent
with hashes.

Jesus.