[prev in list] [next in list] [prev in thread] [next in thread] 

List:       ruby-talk
Subject:    Re: Why nil
From:       Matthew Kerwin <matthew () kerwin ! net ! au>
Date:       2018-12-03 8:49:58
Message-ID: CACweHNA3+So9G2+vQbJ=OC9LKsB6MEjvMXxjimvAw2Oq0FE+CQ () mail ! gmail ! com
[Download RAW message or body]

On Mon, 3 Dec 2018 at 14:47, Ken D'Ambrosio <ken@jots.org> wrote:
> 
> On 2018-07-04 08:06, dade wrote:
> 
> > Hello, let's look at an example
> > 
> > class A
> > attr_accessor :a
> > 
> > def initialize(a)
> > @a = a
> > end
> > 
> > def method1(val)
> > a = val
> > end
> > 
> > def method2(val)
> > a = a + val
> > end
> > end
> > 
> > a = A.new(1)
> > a.method1(2) #=> 3
> > a.method2(2) #=> undefined method `+' for nil:NilClass
> > 
> > Why the second a is nil?
> 
> 
> NOTE: I am not a programmer; I just dabble.  But, unless I miss my mark, the "a" \
> being used in the initialization isn't available elsewhere in the class.  So, when \
> you say a = a + val
> you are, in essence, saying
> undefinedvariable = undefinedvariable + val

Two things:

1. there's no such thing as an undefined variable to the left of an
assignment.  `a =` explicitly defines the variable `a`

2. by the time the interpreter gets to the second `a` it *is* defined,
because of the `a =` that immediately precedes it.  However it's not
*initialised* yet.

> Which is a non-starter.
> 
[snip]
> 
> The fact that (if I had used attr_accessor) ":a" can be accessible as foo.a is \
> simply a nicety of attr_accessor; it doesn't reflect what's going on in the class, \
> itself. 

Third thing:

3. the `attr_accessor :a` has defined `#.a` and `#.a=` methods,
however in this code neither of them are being called because Ruby
biases towards local variables; so `a =` will always define/assign to
a local variable, and any bare `a` (i.e. with no receiver nor
parentheses) that comes after it will always use that local variable.

These would work as (presumably?) intended:

~~~ruby
  def method1(val)
    self.a = val
  end

  def method2(val)
    self.a = self.a + val
    # OR:
    #self.a = a() + val
  end
~~~

> 
> I'm sure, if I'm mistaken, someone will show me the error of my ways,
> 
> -Ken
> 
> > dade.

Not mistaken, just glossing some of the finesse.

Cheers
-- 
  Matthew Kerwin
  https://matthew.kerwin.net.au/

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk>


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic