From: Phrogz Date: 2007-10-16T06:30:04+09:00 Subject: Re: nil.to_i returning zero On Oct 15, 2:39 pm, "Gerardo Santana Gómez Garrido" wrote: > 2007/10/15, Phrogz : > > # Assume nil.to_i is not available > > def foo( bar, jim ) > > bar = 0 if bar.nil? # explicit setting > > a = bar.to_i * 2 > > b = jim.to_i * 2 # I want it to blow up if jim is nil > > end > > I would write that as: > > # Assume nil.to_i is not available > def foo( jim, bar = 0) > a = bar.to_i * 2 > b = jim.to_i * 2 # I want it to blow up if jim is nil > end Ah, but that's subtly different for the edge case where nil is explicitly passed in: irb(main):001:0> def foo( bar=0 ) bar end => nil irb(main):002:0> foo() => 0 irb(main):003:0> foo( nil ) => nil > > Various objects have methods that return an instance of a different > > class. The most obvious is the #to_s method. By extension, your > > argument that nil.to_i should not return 0 because 0 is a truth value > > would further imply that false.to_s should not return "false" because > > all strings are also truth values. > > Not really, if we understand #to_s as a form of serialization. > nil.to_s doesn't return "nil", nor "0", but "". I don't understand your reasoning (though I understand what serialization is). It seems to me like you are saying "NilClass#to_i has the meaning xxx, NilClass.to_s has the meaning yyy, and these are different from what it 'means' to use Float#to_i or Float#to_s." I would say this, instead: AnyClass#to_xxx should return an instance of some class (related to xxx) that is somehow logically related to this particular instance. It doesn't matter what AnyClass is, or what xxx is. There is no inherent meaning in the method beyond that. It's not intended to be used for one thing (serialization) or another (boolean tests). The only requirement for adding such a method is that some reasonable justification can be made for why an instance of class 'xxx' can be created from an instance of AnyClass. (It would not make much sense, IMO, to add FalseClass#to_hash or a Float#to_a, because there does not seem to be a logical transformation from the instance of one class to an instance of the other.) I would say that a reasonable argument can be made that 0 (the instance of the Integer/Fixnum class) is a reasonable result if I asked for nil.to_i. > > If I were to advocate removing nil.to_i, I would probably advocate > > removing nil.to_s for the same reasons...and then I would really, > > I wouldn't. See reason above. I think I'm missing your major argument then. Is your argument: "NilClass#to_i should be removed because it's dangerous; I might call it by accident, and get a result instead of an error." If so, I think the same argument applies equally to #to_s. # If these variables haven't been initialized, # I want an error, not empty strings breaking # my output!!! puts "Hello, #@firstname #@lastname" To be clear, though, I'm *not* advocating removing NilClass#to_s. It provides a reasonable (and usually helpful) string representation of a nil value. If I am worried about nil values: raise "SET NAMES FIRST" if @firstname.nil? || @lastname.nil? puts "Hello, #@firstname #@lastname" If you are concerned that someone might explicitly pass you a nil value when you were expecting something that could be transformed to an integer, you can do the same. Or, as already suggested, you can do this: irb(main):004:0> class NilClass; undef :to_i; end => nil irb(main):005:0> nil.to_i NoMethodError: undefined method `to_i' for nil:NilClass from (irb):5 Of course, that's a workaround, and what you're trying to do is improve the language for everyone based on what you think makes more sense. I simply reiterate that suggestion because it is a possibility of the majority of people (or Matz himself) disagrees with you.