I run into this from time to time and I was wondering if there is a
cleaner way to do check that an object is not nil and also check a
property of that object.
I want to do this:
if !@member.nil? and @member.is_active?
... do something ...
else
... do something else ...
end
But this obviously raises a no method error if @member is nil.
I end up having to do:
if !@member.nil?
if @member.is_active?
... do something ...
else
... do something else ...
end
end
I know it isn't that much more verbose, but does ruby have a more
elegant way of handling this?
···
--
Posted via http://www.ruby-forum.com/.
Hi --
I run into this from time to time and I was wondering if there is a
cleaner way to do check that an object is not nil and also check a
property of that object.
I want to do this:
if !@member.nil? and @member.is_active?
... do something ...
else
... do something else ...
end
But this obviously raises a no method error if @member is nil.
It doesn't, actually, because if @member is nil, the "and" is
short-circuited so the right-hand expression doesn't get evaluated:
if !@member.nil? and @member.is_active?; end
=> nil
@member
=> nil
A somewhat more common way of doing this is:
if @member && @member.is_active? ... end
There's a difference, though, which is that "if @member" is false if
@member is false, not just if @member is nil. I'm a big non-fan of
tri-state booleans involving true/false/nil, so I try to avoid
situations where I have to distinguish between nil and false for
condition-testing purposes.
David
···
On Thu, 19 Aug 2010, Cory Patterson wrote:
--
David A. Black, Senior Developer, Cyrus Innovation Inc.
The Ruby training with Black/Brown/McAnally
Compleat Philadelphia, PA, October 1-2, 2010
Rubyist http://www.compleatrubyist.com
I've run into a similar situation before, and found that
short-circuiting in an 'if' statement is inconsistent.
For instance, this will short-circuit and prevent evaluation of
subsequent statements if the first one is false (which is desired
obviously):
unless creds.class.to_s =~ /Hash/ && creds.has_key?("user") && ...
But this won't:
unless creds.instance_of?(Hash) && creds.has_key?("user") && ...
I'd be interested to learn why the first one short-circuits and the
second doesn't. Anyone have any insight?
Thanks,
Alex
···
On Wed, 2010-08-18 at 16:09 -0500, Cory Patterson wrote:
I run into this from time to time and I was wondering if there is a
cleaner way to do check that an object is not nil and also check a
property of that object.
I want to do this:
if !@member.nil? and @member.is_active?
... do something ...
else
... do something else ...
end
But this obviously raises a no method error if @member is nil.
I end up having to do:
if !@member.nil?
if @member.is_active?
... do something ...
else
... do something else ...
end
end
I know it isn't that much more verbose, but does ruby have a more
elegant way of handling this?
Hi --
I've run into a similar situation before, and found that
short-circuiting in an 'if' statement is inconsistent.
For instance, this will short-circuit and prevent evaluation of
subsequent statements if the first one is false (which is desired
obviously):
unless creds.class.to_s =~ /Hash/ && creds.has_key?("user") && ...
But this won't:
unless creds.instance_of?(Hash) && creds.has_key?("user") && ...
They both short-circuit. Note that the puts("here") statement never gets
executed.
creds = {}
=> {}
unless creds.class.to_s =~ /Hash/ && creds.has_key?("user") && puts("here"); 1; end
=> 1
unless creds.instance_of?(Hash) && creds.has_key?("user") && puts("here"); 1; end
=> 1
David
···
On Thu, 19 Aug 2010, Alex Stahl wrote:
--
David A. Black, Senior Developer, Cyrus Innovation Inc.
The Ruby training with Black/Brown/McAnally
Compleat Philadelphia, PA, October 1-2, 2010
Rubyist http://www.compleatrubyist.com
David,
You are completely correct. I guess that was a bad example. So the
order of the conditions is important:
if @member and @member.is_active?; end
=> nil
if @member.is_active? && @member; end
NoMethodError: undefined method `is_active?' for nil:NilClass
I could have sworn I ran into this somewhere and it didn't work as
expected.
Thanks so much for the insight, it is good information to have.
Cory
David A. Black wrote:
···
Hi --
On Thu, 19 Aug 2010, Cory Patterson wrote:
end
But this obviously raises a no method error if @member is nil.
It doesn't, actually, because if @member is nil, the "and" is
short-circuited so the right-hand expression doesn't get evaluated:
if !@member.nil? and @member.is_active?; end
=> nil
@member
=> nil
A somewhat more common way of doing this is:
if @member && @member.is_active? ... end
There's a difference, though, which is that "if @member" is false if
@member is false, not just if @member is nil. I'm a big non-fan of
tri-state booleans involving true/false/nil, so I try to avoid
situations where I have to distinguish between nil and false for
condition-testing purposes.
David
--
David A. Black, Senior Developer, Cyrus Innovation Inc.
The Ruby training with Black/Brown/McAnally
Compleat Philadelphia, PA, October 1-2, 2010
Rubyist http://www.compleatrubyist.com
--
Posted via http://www.ruby-forum.com/.
(P.S. I've made the second condition fail, rather than the first, but if
you make creds a non-hash it will short-circuit after the first one.)
···
On Thu, 19 Aug 2010, David A. Black wrote:
Hi --
On Thu, 19 Aug 2010, Alex Stahl wrote:
I've run into a similar situation before, and found that
short-circuiting in an 'if' statement is inconsistent.
For instance, this will short-circuit and prevent evaluation of
subsequent statements if the first one is false (which is desired
obviously):
unless creds.class.to_s =~ /Hash/ && creds.has_key?("user") && ...
But this won't:
unless creds.instance_of?(Hash) && creds.has_key?("user") && ...
They both short-circuit. Note that the puts("here") statement never gets
executed.
creds = {}
=> {}
unless creds.class.to_s =~ /Hash/ && creds.has_key?("user") && puts("here"); 1; end
=> 1
unless creds.instance_of?(Hash) && creds.has_key?("user") && puts("here"); 1; end
=> 1
--
David A. Black, Senior Developer, Cyrus Innovation Inc.
The Ruby training with Black/Brown/McAnally
Compleat Philadelphia, PA, October 1-2, 2010
Rubyist http://www.compleatrubyist.com
David,
You are completely correct. I guess that was a bad example. So the
order of the conditions is important:
if @member and @member.is_active?; end
=> nil
if @member.is_active? && @member; end
NoMethodError: undefined method `is_active?' for nil:NilClass
Yes, it's important. Ruby starts evaluating from left to right, and
will shortcircuit on the first value that would make the whole
expression false (or true if it's an "or").
irb(main):004:0> member = nil
=> nil
irb(main):005:0> if member or member.is_active?
irb(main):006:1> puts "one or both were true"
irb(main):007:1> end
NoMethodError: undefined method `is_active?' for nil:NilClass
from (irb):5
irb(main):008:0> member = "test"
=> "test"
irb(main):009:0> if member or member.is_active?
irb(main):010:1> puts "one or both were true"
irb(main):011:1> end
one or both were true
Here you have the opposite situation: when the first truthy expression
is found, the evaluation is shortcircuited to that value, as you can
see that the is_active? method is not called in the last example.
Jesus.
···
On Wed, Aug 18, 2010 at 11:47 PM, Cory Patterson <coryp@aquasun.com> wrote:
from :0
Strange... it was failing before (like a few weeks ago) w/ a
NoMethodError on has_key? when it wasn't a hash. But trying it again
now works fine as you note.
···
On Wed, 2010-08-18 at 16:33 -0500, David A. Black wrote:
On Thu, 19 Aug 2010, David A. Black wrote:
> Hi --
>
> On Thu, 19 Aug 2010, Alex Stahl wrote:
>
>> I've run into a similar situation before, and found that
>> short-circuiting in an 'if' statement is inconsistent.
>>
>> For instance, this will short-circuit and prevent evaluation of
>> subsequent statements if the first one is false (which is desired
>> obviously):
>>
>> unless creds.class.to_s =~ /Hash/ && creds.has_key?("user") && ...
>>
>>
>> But this won't:
>>
>> unless creds.instance_of?(Hash) && creds.has_key?("user") && ...
>
> They both short-circuit. Note that the puts("here") statement never gets
> executed.
>
>>> creds = {}
> => {}
>>> unless creds.class.to_s =~ /Hash/ && creds.has_key?("user") &&
>>> puts("here"); 1; end
> => 1
>>> unless creds.instance_of?(Hash) && creds.has_key?("user") && puts("here");
>>> 1; end
> => 1
(P.S. I've made the second condition fail, rather than the first, but if
you make creds a non-hash it will short-circuit after the first one.)
For the record: short circuiting also happens in Enumerable#any? and
#all?. And btw, the same short circuiting is done in Java and I guess
most modern languages.
Kind regards
robert
···
2010/8/19 Jesús Gabriel y Galán <jgabrielygalan@gmail.com>:
On Wed, Aug 18, 2010 at 11:47 PM, Cory Patterson <coryp@aquasun.com> wrote:
David,
You are completely correct. I guess that was a bad example. So the
order of the conditions is important:
if @member and @member.is_active?; end
=> nil
if @member.is_active? && @member; end
NoMethodError: undefined method `is_active?' for nil:NilClass
Yes, it's important. Ruby starts evaluating from left to right, and
will shortcircuit on the first value that would make the whole
expression false (or true if it's an "or").
--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/