Ruby Nil and Zero - ruby

What's the science behind the fact that the to_i method in Ruby's NilClass instances returns zero? Returning nil or raising an exception would not be more logical?

It fits the Ruby philosophy of permissiveness (as opposed to, for example, the strictness of Python):
nil.to_i #=> 0
"".to_i #=> 0
"123hello".to_i #=> 123
"hello".to_i #=> 0
As noted by Zabba, you can use Kernel#Integer(string) for strict conversion.

NilClass defines #to_i for the same reason it defines a #to_a that returns []. It's giving you something of the right type but an empty sort of value.
This is actually quite useful. For example:
<%= big.long.expr.nil? ? "" : big.long.expr %>
becomes:
<%= big.long.expr %>
Much nicer! (Erb is calling #to_s which, for nil, is "".) And:
if how.now.brown.cow && how.now.brown.cow[0]
how.now.brown.cow[0]
else
0
end
becomes:
how.now.brown.cow.to_a[0].to_i
The short conversions exist when only a representation is needed. The long conversions are the ones that the Ruby core methods call and they require something very close. Use them if you want a type check.
That is:
thing.to_int # only works when almost Integer already. NilClass throws NoMethodError
thing.to_i # this works for anything that cares to define a conversion

to_i means "convert me to an integer if you can".
If you want "if you're very much integer-like, give me your integer value, else give a NoMethodError", then use .to_int.
There's another question that asks about the difference between to_i and to_int, to_s versus to_str, etc. Let me know if you'd like me to find it for you.

The protocol of to_i says that you must return an Integer and you must not raise an exception. Both of your suggestions violate at least one of those rules. So, no, those would not only not be more logical, they would be simply invalid.
Note, however, that nil does not respond to to_int. If it did respond to to_int, that would, indeed, be "illogical".

If you happen to be in Rails then you can use try:
nil.to_i # => 0
nil.try :to_i # => nil

A concise Ruby 2.3+ method for returning nil for nil.to_i instead of 0, is to use the safe navigation operator:
irb(main):001:0> nil.to_i
=> 0
irb(main):002:0> nil&.to_i
=> nil

Related

`non-object-ness` of `nil` in ruby

From one of the online resource of Ruby I found the below statement:
The special object nil is, indeed, an object (it’s the only instance of a class called
NilClass). But in practice, it’s also a kind of non-object. The boolean value of nil is
false, but that’s just the start of its non-object-ness.
While nil responds to method calls as below,like other objects,what non-objectness author tried to say :
nil.to_s #=> ""
nil.to_i #=> 0
nil.object_id #=> 4
nil.inspect #=> "nil"
Can anyone help me here to understand the philosophy - non-object-ness of nil ?
nil is equivalent with null in other languages. Usually, null should not treated as a sane value.
However - as you may noticed - the syntax of Ruby language does everything over the method calls on objects, a lot more things than Python. Determining a sanity of values is a part of it.
Consider the following example
def foobar(arg)
if arg < 1
return nil
else
return "Oh, hi!"
end
end
res = foobar(rand(2))
puts res unless res.nil?
As you see, in the last line I check the nil-ness of the result with calling a nil? method. This is a most effective way to do it, because comparation operators can be overloaded and can do a very different things. The nil? returns with true only if the value can be treated as nil (usually, if the value is nil - but nil? method is overridable too, even if it is highly discouraged. Developers usually are not override this method).
Another useful property of nil it is has a to_s method, so you can x = "#{nil} and it results an empty string.
If nil weren't be an object, you cannot call nil? or other useful functions on that, but you can faced with a NullPointerException like in Java or a segmentation fault like in C/C++. And usually it is pointless.

What does the nil returned by puts signify?

When I use the puts command, especially in IRB I get a nil returned as part of the statement execution.
I was curious to know what it means on a general note.
Please find below a sample:-
ruby-1.8.7-p334 :021 > puts 3/2
1
=> nil
Your inputs would be really handy.
Thanks.
Every method in Ruby returns a value. puts doesn't really have any sort of useful value to return, so it returns nil.

Ruby !sub returning strange null

I don't understand the result of the first line. It's supposed to return a file name without extension if the file has one. Can somebody explain to me why it is like that and also tell me what would be a more proper here?
irb(main):003:0> 'fafeafeafewafeawfeaw'.sub!(/\.[^\.]*$/, '')
=> nil
irb(main):004:0> '.fafeafeafewafeawfeaw'.sub!(/\.[^\.]*$/, '')
=> ""
irb(main):005:0> 'fafeafeafewafea.wfeaw'.sub!(/\.[^\.]*$/, '')
=> "fafeafeafewafea"
It is documented that the sub! (like many of the ! string operations) return nil if no change was made.
From the docs
Performs the substitutions of String#sub in place, returning str, or nil if no substitutions were performed.
Instead use the regular sub. In your case the extra bang (!) is unnecessary.
'fafeafeafewafeawfeaw'.sub(/\.[^\.]*$/, '')
Bang Methods
The difference between sub and sub! is subtle. But in ruby in general, the non bang (!) version of a method is safer. Since by convention the bang means the method has more side affects.
In the case of string functions (and many array/enumerable functions) the bang means the method operates on the contents of the caller, instead of making (and returning) a copy.
s = 'fafafa'
puts s #=> 'fafafa'
puts s.sub(/fa/, 'fo') #=> 'fofofo'
puts s #=> 'fafafa'
puts s.sub!(/fa/, 'fo') #=> 'fofofo'
puts s #=> 'fofofo'

What does !! mean in ruby?

Just wondering what !! is in Ruby.
Not not.
It's used to convert a value to a boolean:
!!nil #=> false
!!"abc" #=> true
!!false #=> false
It's usually not necessary to use though since the only false values to Ruby are nil and false, so it's usually best to let that convention stand.
Think of it as
!(!some_val)
One thing that is it used for legitimately is preventing a huge chunk of data from being returned. For example you probably don't want to return 3MB of image data in your has_image? method, or you may not want to return your entire user object in the logged_in? method. Using !! converts these objects to a simple true/false.
It returns true if the object on the right is not nil and not false, false if it is nil or false
def logged_in?
!!#current_user
end
! means negate boolean state, two !s is nothing special, other than a double negation.
!true == false
# => true
It is commonly used to force a method to return a boolean. It will detect any kind of truthiness, such as string, integers and what not, and turn it into a boolean.
!"wtf"
# => false
!!"wtf"
# => true
A more real use case:
def title
"I return a string."
end
def title_exists?
!!title
end
This is useful when you want to make sure that a boolean is returned. IMHO it's kind of pointless, though, seeing that both if 'some string' and if true is the exact same flow, but some people find it useful to explicitly return a boolean.
Note that this idiom exists in other programming languages as well. C didn't have an intrinsic bool type, so all booleans were typed as int instead, with canonical values of 0 or 1. Takes this example (parentheses added for clarity):
!(1234) == 0
!(0) == 1
!(!(1234)) == 1
The "not-not" syntax converts any non-zero integer to 1, the canonical boolean true value.
In general, though, I find it much better to put in a reasonable comparison than to use this uncommon idiom:
int x = 1234;
if (!!x); // wtf mate
if (x != 0); // obvious
It's useful if you need to do an exclusive or. Copying from Matt Van Horn's answer with slight modifications:
1 ^ true
TypeError: can't convert true into Integer
!!1 ^ !!true
=> false
I used it to ensure two variables were either both nil, or both not nil.
raise "Inconsistency" if !!a ^ !!b
It is "double-negative", but the practice is being discouraged. If you're using rubocop, you'll see it complain on such code with a Style/DoubleNegation violation.
The rationale states:
As this is both cryptic and usually redundant, it should be avoided
[then paraphrasing:] Change !!something to !something.nil?
Understanding how it works can be useful if you need to convert, say, an enumeration into a boolean. I have code that does exactly that, using the classy_enum gem:
class LinkStatus < ClassyEnum::Base
def !
return true
end
end
class LinkStatus::No < LinkStatus
end
class LinkStatus::Claimed < LinkStatus
def !
return false
end
end
class LinkStatus::Confirmed < LinkStatus
def !
return false
end
end
class LinkStatus::Denied < LinkStatus
end
Then in service code I have, for example:
raise Application::Error unless !!object.link_status # => raises exception for "No" and "Denied" states.
Effectively the bangbang operator has become what I might otherwise have written as a method called to_bool.
Other answers have discussed what !! does and whether it is good practice or not.
However, none of the answers give the "standard Ruby way" of casting a value into a boolean.
true & variable
TrueClass, the class of the Ruby value true, implements a method &, which is documented as follows:
Returns false if obj is nil or false, true otherwise.
Why use a dirty double-negation when the standard library has you covered?

Is There a Better Way of Checking Nil or Length == 0 of a String in Ruby?

Is there a better way than the following to check to see if a string is nil OR has a length of 0 in Ruby?
if !my_string || my_string.length == 0
return true
else
return false
end
In C# there's the handy
string.IsNullOrEmpty(myString)
Anything similar to that in Ruby?
When I'm not worried about performance, I'll often use this:
if my_string.to_s == ''
# It's nil or empty
end
There are various variations, of course...
if my_string.to_s.strip.length == 0
# It's nil, empty, or just whitespace
end
If you are willing to require ActiveSupport you can just use the #blank? method, which is defined for both NilClass and String.
I like to do this as follows (in a non Rails/ActiveSupport environment):
variable.to_s.empty?
this works because:
nil.to_s == ""
"".to_s == ""
An alternative to jcoby's proposal would be:
class NilClass
def nil_or_empty?
true
end
end
class String
def nil_or_empty?
empty?
end
end
As it was said here before Rails (ActiveSupport) have a handy blank? method and it is implemented like this:
class Object
def blank?
respond_to?(:empty?) ? empty? : !self
end
end
Pretty easy to add to any ruby-based project.
The beauty of this solution is that it works auto-magicaly not only for Strings but also for Arrays and other types.
variable.blank? will do it.
It returns true if the string is empty or if the string is nil.
nil? can be omitted in boolean contexts. Generally, you can use this to replicate the C# code:
return my_string.nil? || my_string.empty?
First of all, beware of that method:
As Jesse Ezel says:
Brad Abrams
"The method might seem convenient, but most of the time I have found that this situation arises from trying to cover up deeper bugs.
Your code should stick to a particular protocol on the use of strings, and you should understand the use of the protocol in library code and in the code you are working with.
The NullOrEmpty protocol is typically a quick fix (so the real problem is still somewhere else, and you got two protocols in use) or it is a lack of expertise in a particular protocol when implementing new code (and again, you should really know what your return values are)."
And if you patch String class... be sure NilClass has not been patch either!
class NilClass
def empty?; true; end
end
Every class has a nil? method:
if a_variable.nil?
# the variable has a nil value
end
And strings have the empty? method:
if a_string.empty?
# the string is empty
}
Remember that a string does not equal nil when it is empty, so use the empty? method to check if a string is empty.
Another option is to convert nil to an empty result on the fly:
(my_string||'').empty?
Konrad Rudolph has the right answer.
If it really bugs you, monkey patch the String class or add it to a class/module of your choice. It's really not a good practice to monkey patch core objects unless you have a really compelling reason though.
class String
def self.nilorempty?(string)
string.nil? || string.empty?
end
end
Then you can do String.nilorempty? mystring
Check for Empty Strings in Plain Ruby While Avoiding NameError Exceptions
There are some good answers here, but you don't need ActiveSupport or monkey-patching to address the common use case here. For example:
my_string.to_s.empty? if defined? my_string
This will "do the right thing" if my_string is nil or an empty string, but will not raise a NameError exception if my_string is not defined. This is generally preferable to the more contrived:
my_string.to_s.empty? rescue NameError
or its more verbose ilk, because exceptions should really be saved for things you don't expect to happen. In this case, while it might be a common error, an undefined variable isn't really an exceptional circumstance, so it should be handled accordingly.
Your mileage may vary.
If you are using rails, you can use #present?
require 'rails'
nil.present? # ==> false (Works on nil)
''.present? # ==> false (Works on strings)
' '.present? # ==> false (Works on blank strings)
[].present? # ==> false(Works on arrays)
false.present? # ==> false (Works on boolean)
So, conversely to check for nil or zero length use !present?
!(nil.present?) # ==> true
!(''.present?) # ==> true
!(' '.present?) # ==> true
!([].present?) # ==> true
!(false.present?) # ==> true
Have you tried Refinements?
module Nothingness
refine String do
alias_method :nothing?, :empty?
end
refine NilClass do
alias_method :nothing?, :nil?
end
end
using Nothingness
return my_string.nothing?
In rails you can try #blank?.
Warning: it will give you positives when string consists of spaces:
nil.blank? # ==> true
''.blank? # ==> true
' '.blank? # ==> true
'false'.blank? # ==> false
Just wanted to point it out. Maybe it suits your needs
UPD. why am i getting old questions in my feed?
Sorry for necroposting.
For code golfers:
if my_string=~/./
p 'non-empty string'
else
p 'nil or empty string'
end
Or if you're not a golfer (requires ruby 2.3 or later):
if my_string&.size&.positive?
# nonzero? also works
p 'non-empty string'
else
p 'nil or empty string'
end

Resources