Re: Why nil


(Stefano Crocco) #1

Why should it be something else than nil? inside method2, a is a local
variable. To execute the line a = a + val, ruby first compute the right hand
side of the expression, which is a + val. Since you haven't given a value to
the variable a, it is implicitly set to nil. Ruby then tries to sum nil to
value and it fails.

I think that you expected method1 and method2 to call the accessor methods,
but this is not what happens. When ruby sees a = ..., it assumes that a is a
local variable, and doesn't even notice that there are methods called "a" and
"a=". To avoid this and have the accessor methods called from method1 and
method2, you have to explicitly tell ruby those "a" are methods by calling
them with the dot notation (using self as receiver):

class A
attr_accessor :a

def initialize(a)
@a = a
end

def method1(val)
self.a = val
end

def method2(val)
self.a = a + val
end
end

I hope this helps

Stefano

···

On mercoledì 4 luglio 2018 14:06:39 CEST 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?

dade.


(Tanguy Andreani) #2

Well just use @a everywhere in method1 and method2 and you won’t need an accessor.


(Andy Jones) #3

I think that you expected method1 and method2 to call the accessor methods,

This is why I prefer to always use @ to refer to attributes inside their class, contrary to what some quite respected Rubyists suggest.

Click here to view Company Information and Confidentiality Notice.<http://www.jameshall.co.uk/index.php/small-print/email-disclaimer>

Please note that we have updated our privacy policy in line with new data protection regulations. Please refer to our website to view the ways in which we handle your data.


(Dmitriy Non) #4

The problem is that setter/getter can become more complicated
than just assigning or getting value.

If your code uses getter/setter more than 1 time you should not use
instance variable directly.

In the end, using it directly has no benefits at all if you know ruby.
Well, except for absence of one code line `attr_accessor :a`.

···

--------------------------------------
Dmitriy Non
non.dmitriy@gmail.com

On 4 Jul 2018, at 16:02, Andy Jones <Andy.Jones@jameshall.co.uk> wrote:

I think that you expected method1 and method2 to call the accessor methods,

This is why I prefer to always use @ to refer to attributes inside their class, contrary to what some quite respected Rubyists suggest.

Click here to view Company Information and Confidentiality Notice.<http://www.jameshall.co.uk/index.php/small-print/email-disclaimer>

Please note that we have updated our privacy policy in line with new data protection regulations. Please refer to our website to view the ways in which we handle your data.

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


(Andy Jones) #5

The problem is that setter/getter can become more complicated
than just assigning or getting value.

If your code uses getter/setter more than 1 time you should not use
instance variable directly.

In the end, using it directly has no benefits at all if you know ruby.
Well, except for absence of one code line `attr_accessor :a`.

But as already noted, you are forced to use @var = 1 and not var = 1 inside the class. I agree it might be nice to abstract out attributes to their getters and setters inside the class, but since you can only do it for getters, the value of that is limited.

Also, the abstraction is mildly confusing. If I have an attribute @foo in a subclass and I make reference to foo, without the @, is that a getter? Or is it something defined in the superclass? Or in a mixin? I have to look at the whole class definition, at least, to check.

Final point: surely the only legitimate reason to use attr_accessor etc is if something _outside_ of the class needs to access the attribute? I know Ruby doesn't do strong encapsulation, but, even so...

Click here to view Company Information and Confidentiality Notice.<http://www.jameshall.co.uk/index.php/small-print/email-disclaimer>

Please note that we have updated our privacy policy in line with new data protection regulations. Please refer to our website to view the ways in which we handle your data.


(Wolf) #6

Why are you forced to do that? You can just use `self.var = 1`.

W.

···

On , Andy Jones wrote:

>>>>>>>>
The problem is that setter/getter can become more complicated
than just assigning or getting value.

If your code uses getter/setter more than 1 time you should not use
instance variable directly.

In the end, using it directly has no benefits at all if you know ruby.
Well, except for absence of one code line `attr_accessor :a`.
<<<<

But as already noted, you are forced to use @var = 1 and not var = 1 inside the class.

--
There are only two hard things in Computer Science:
cache invalidation, naming things and off-by-one errors.


(Robert K.) #7

> >>>>>>>>
> The problem is that setter/getter can become more complicated
> than just assigning or getting value.
>
> If your code uses getter/setter more than 1 time you should not use
> instance variable directly.
>
> In the end, using it directly has no benefits at all if you know ruby.
> Well, except for absence of one code line `attr_accessor :a`.
> <<<<
>
> But as already noted, you are forced to use @var = 1 and not var = 1 inside the class.

Why are you forced to do that?

Because it's the way the language is built.

You can just use `self.var = 1`.

You can, but then you need a method "var=" and the state needs to be
stored somewhere, presumably in an instance variable @var.

Cheers

robert

···

On Sun, Jul 8, 2018 at 2:14 PM Wolf <wolf@wolfsden.cz> wrote:

On , Andy Jones wrote:

--
[guy, jim, charlie].each {|him| remember.him do |as, often| as.you_can
- without end}
http://blog.rubybestpractices.com/


(Ryan Davis) #8

I’m one of those. I totally disagree with your assessment. Always use accessors and you have only one thing to change when you need to modify how storage is done, whether that’s adding caching, adding or offloading calculation, or just having a single point to add a breakpoint to debug.

Using instance variables directly everywhere means you’ve got N places you need to pay attention to, not 1. It also means that you’re using a double standard when it comes to accessing your state (assuming you still have a public accessor method) that can lead to inconsistencies. The only place you’ll find an “@“ in most of my code is inside of a custom setter method and that has worked out very very well for me over the long haul (looong before I was doing ruby, I was doing smalltalk, and this pattern comes from there).

···

On Jul 4, 2018, at 06:02, Andy Jones <Andy.Jones@jameshall.co.uk> wrote:

I think that you expected method1 and method2 to call the accessor methods,

This is why I prefer to always use @ to refer to attributes inside their class, contrary to what some quite respected Rubyists suggest.


(Ryan Davis) #9

I’m not sure why you’re phrasing any of this this way. Given the OP’s original code, it was ALREADY structured that way and the advice given by Gonzola and Wolf was spot on. Your “yes but” seems ill-placed and, if anything, should be directed at all the responses that say you’re forced to use @vars (which I always eschew when possible).

···

On Jul 9, 2018, at 07:30, Robert Klemme <shortcutter@googlemail.com> wrote:

On Sun, Jul 8, 2018 at 2:14 PM Wolf <wolf@wolfsden.cz> wrote:

On , Andy Jones wrote:

The problem is that setter/getter can become more complicated
than just assigning or getting value.

If your code uses getter/setter more than 1 time you should not use
instance variable directly.

In the end, using it directly has no benefits at all if you know ruby.
Well, except for absence of one code line `attr_accessor :a`.
<<<<

But as already noted, you are forced to use @var = 1 and not var = 1 inside the class.

Why are you forced to do that?

Because it's the way the language is built.

You can just use `self.var = 1`.

You can, but then you need a method "var=" and the state needs to be
stored somewhere, presumably in an instance variable @var.


(Ryan Davis) #10

That is decidedly false: `self.var = 1`. The ONLY place you’re “forced” to use an ivar, is in the implementation of a custom setter:

def var= o
  @var = calculate o
end

···

On Jul 5, 2018, at 00:21, Andy Jones <Andy.Jones@jameshall.co.uk> wrote:

But as already noted, you are forced to use @var = 1 and not var = 1 inside the class. I agree it might be nice to abstract out attributes to their getters and setters inside the class, but since you can only do it for getters, the value of that is limited.


(Andy Jones) #11

Folks, I was stating a personal preference. I think I'm allowed those. Not attacking anyone. If I want to use @attribute = "foo" and not self.attribute = "foo" inside a class, that's not objectively wrong. It's my personal choice.

Click here to view Company Information and Confidentiality Notice.<http://www.jameshall.co.uk/index.php/small-print/email-disclaimer>

Please note that we have updated our privacy policy in line with new data protection regulations. Please refer to our website to view the ways in which we handle your data.


(Xavier Noria) #12

Folks, I was stating a personal preference. I think I'm allowed those.

Not attacking anyone. If I want to use @attribute = "foo" and not
self.attribute = "foo" inside a class, that's not objectively wrong. It's
my personal choice.

FWIW I use ivars often too, tend to define accessors only if they are
public interface.

Even further, if the test suite of the class needs to set state by
reading/writing an ivar for whatever reason, and that is the only code
accessing them outside the class, I still stick to ivars and use
instance_variable_get/set. That is because my public interface is strictly
defined by client code and in my book a test is not client code, and
because I believe it is OK that the test suite knows the ivars of the class
it is covering if the interface so requires it.

Other people with different style/preferences, fine!

···

On Wed, Jul 11, 2018 at 9:35 AM, Andy Jones <Andy.Jones@jameshall.co.uk> wrote:


(Andy Jones) #13

That is because my public interface is strictly defined by client code and in my book a test is not client code, and because I believe it is OK that the test suite knows the ivars of the class it is covering if the interface so requires it.

I had that conversation with myself a while ago and decided that my tests _were_ client code, just as important as the other classes that called that class.

Either way seems like a perfectly valid call to me…

Click here to view Company Information and Confidentiality Notice.<http://www.jameshall.co.uk/index.php/small-print/email-disclaimer>

Please note that we have updated our privacy policy in line with new data protection regulations. Please refer to our website to view the ways in which we handle your data.


(Robert K.) #14

>>>>>
That is because my public interface is strictly defined by client code and in my book a test is not client code, and because I believe it is OK that the test suite knows the ivars of the class it is covering if the interface so requires it.
<<<<<<

I had that conversation with myself a while ago and decided that my tests _were_ client code, just as important as the other classes that called that class.

I'm too old for religious wars but I will say that I tend to view test
code not as a first class client. But: I usually create class
interfaces as abstract data types and there you typically define one
constraint in a number of operations; if you do that then I believe
this will support testing. After all, you want to ensure that the
observed behavior is as intended and not poke into the innards of the
implementation. If there are cases where an occasional additional
method is needed for some validation I won't commit Seppuku over this.
:slight_smile:

Either way seems like a perfectly valid call to me…

Right, we're still in the land of the Pragmatic Programmer, aren't we?

Kind regards

robert

https://pragprog.com/book/tpp/the-pragmatic-programmer

···

On Wed, Jul 11, 2018 at 9:59 AM Andy Jones <Andy.Jones@jameshall.co.uk> wrote:

--
[guy, jim, charlie].each {|him| remember.him do |as, often| as.you_can
- without end}
http://blog.rubybestpractices.com/


(Ken D'Ambrosio) #15

Please DO NOT send any more e-mail to me. Thanks.
_Chinmoy_

You are subscribed to a Ruby mailing list; as long as the list is active
(which I hope is for some time to come), you will receive e-mail. At
the bottom of every e-mail you receive from the list -- including this
one when it comes through the list -- are the following two lines:

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

E-mail to the first, or click on the second, and you can unsubscribe.

Mailing the list, alas, simply generates more e-mail. (Indeed, mail
storms sometimes occur from people who don't quite get this. But this
list is low-volume enough I'm not overly worried, and, sometimes, it
doesn't hurt to remind folks at large how to go about unsubscribing.)

Have a pleasant weekend!

-Ken

···

On 2018-07-13 13:46, Sarkar Chinmoy wrote:

On Wednesday, July 11, 2018, 2:59:58 AM CDT, Andy Jones <Andy.Jones@jameshall.co.uk> wrote:

That is because my public interface is strictly defined by client code and in my book a test is not client code, and because I believe it is OK that the test suite knows the ivars of the class it is covering if the interface so requires it.

<<<<<<

I had that conversation with myself a while ago and decided that my tests __were__ client code, just as important as the other classes that called that class.

Either way seems like a perfectly valid call to me...

Click here to view Company Information and Confidentiality Notice. [1]
Please note that we have updated our privacy policy in line with new data protection regulations. Please refer to our website to view the ways in which we handle your data.

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

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

Links:
------
[1] http://www.jameshall.co.uk/index.php/small-print/email-disclaimer