Why not check for nil?


#1

A post I ran across on a rails forum reads:

“Warning! DO NOT test for nil! This is a very bad coding practice. You
can use “if obj”, but do not use “if obj.nil?” or whatever.”

Is that generally true? Why? m.


#2

matt neuburg wrote:

A post I ran across on a rails forum reads:

“Warning! DO NOT test for nil! This is a very bad coding practice. You
can use “if obj”, but do not use “if obj.nil?” or whatever.”

Is that generally true? Why? m.

because it might be false [not nil]?
-=r


#3

Roger P. removed_email_address@domain.invalid wrote:

matt neuburg wrote:

A post I ran across on a rails forum reads:

“Warning! DO NOT test for nil! This is a very bad coding practice. You
can use “if obj”, but do not use “if obj.nil?” or whatever.”

Is that generally true? Why? m.

because it might be false [not nil]?

Yes, I thought of that too. But of course to me that is why I would
check for nil (I really really do want to know if it’s nil).

Maybe the poster just didn’t know what he was talking about… m.


#4

Roger P. wrote:

matt neuburg wrote:

A post I ran across on a rails forum reads:

“Warning! DO NOT test for nil! This is a very bad coding practice. You
can use “if obj”, but do not use “if obj.nil?” or whatever.”

Is that generally true? Why? m.

because it might be false [not nil]?

Technically yes, but that admonition has more meanings (some of which
may have
escaped that original rails poster).

Consider this pattern:

if @user
render :partial => ‘premium_content’ # for logged-in users
else
render :partial => ‘teaser_content’ # for the great washed masses
end

That is sloppy programming because it asks @user for its type (are you a
logged-in user? or just a slovenly nil?)

The correct pattern is @user is never nil, and if no user is logged in,
then it
should hold a “Guest” object. Then User and Guest can provide different
methods
for the same messages (method names):

render :partial => @user.content_template

That pattern collects many redundant ‘if’ statements into one place;
that
technique is the heart of all OO programming.


#5

David A. Black wrote:

Definitely use #nil? if you want to know whether something is exactly
nil. There are certainly a lot of unnecessary calls to #nil? out there,
but it doesn’t follow that it can never be right to test for nil.

Let’s call this the “non-suicidal Samurai Principle”. Either return
victorious,
or return empty-handed. (And don’t waste my expense training you, duh!)

How many times have we written…

def samurai
blah and blah or blah
end

if samurai

…and then never bothered to check - even with unit tests, whether a
failing
samurai() call returned a nil or a false? Ruby’s break with incorrect
tradition

  • letting 0 be true - cleaned up a whole lot of clutter. .index() can
    easily
    distinguish “found at 0 index” from “not found”. But this means we no
    longer
    always need to track which of those blah() calls returns a nil, which a
    false,
    and which one the boolean short-circuiting collects for us.

#6

Hi –

matt neuburg wrote:

Yes, I thought of that too. But of course to me that is why I would
check for nil (I really really do want to know if it’s nil).

Definitely use #nil? if you want to know whether something is exactly
nil. There are certainly a lot of unnecessary calls to #nil? out there,
but it doesn’t follow that it can never be right to test for nil.

David


David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.rubypal.com
Coming in 2009: The Well-Grounded Rubyist (http://manning.com/black2)

Ruby Training Atlanta! April 1-3, http://www.entp.com/training/atlanta09


#7

Phlip wrote:

How many times have we written…
incorrect tradition - letting 0 be true - cleaned up a whole lot of
clutter. .index() can easily distinguish “found at 0 index” from “not
found”. But this means we no longer always need to track which of those
blah() calls returns a nil, which a false, and which one the boolean
short-circuiting collects for us.

I didn’t say you should always do it, simply that if you want to know
whether an object is exactly nil, use #nil?. If you don’t, don’t :slight_smile:

There’s an interesting case of nil overloading that I’ve never seen any
very nice workarounds for, though it probably occurs rarely if at all:

a = [1,2,3,nil,“abc”]
r = a.find {|e| !e }

r will be nil – but it will also be nil if a doesn’t contain nil.
Fortunately not an everyday problem, but an interesting case of
difficulty distinguishing found from not found.

David


David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.rubypal.com
Coming in 2009: The Well-Grounded Rubyist (http://manning.com/black2)

Ruby Training Atlanta! April 1-3, http://www.entp.com/training/atlanta09