2011-06-17 109 views
13

Ruby的NilClass实例中的to_i方法返回零的事实背后的科学是什么?返回或引发异常不会更符合逻辑?Ruby Nil and Zero

+3

相关:您可以使用'N =整数(STR)'如果你想提高对故障异常。 – Dogbert

回答

12

NilClass定义#to_i出于同样的原因它定义了一个#to_a返回[].它给你正确的类型,但空之类的价值的东西。

这实际上非常有用。例如:

<%= big.long.expr.nil? ? "" : big.long.expr %> 

变为:

<%= big.long.expr %> 

的效果好很多! (ERB是调用#to_s其中对于零,为 “”)。而且:

if how.now.brown.cow && how.now.brown.cow[0] 
    how.now.brown.cow[0] 
else 
    0 
end 

变为:仅需要表示时

how.now.brown.cow.to_a[0].to_i 

短转化存在。长时间转换是Ruby核心方法调用的转换,它们需要非常接近的东西。如果您想要进行类型检查,请使用它们。

即:

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 
+0

*“好多了!”*是的,这取决于你和项目工作的其他人都知道Ruby以及你想要依赖不直观行为的程度。返回0而不是引发异常的'nil.to_i'在逻辑上没有太大的意义。你怎么能从'nil'得到'0'?它不像'nil == 0'返回true,但'to_i'意味着等价。 –

+4

@Ed S .:不,'to_int'意味着等价,'to_i'非常松散,它并不意味着什么。 –

+1

伟大的答案!我总是忽略了长期的转换,现在我可以理解它们以及红宝石哲学中的合适性。 –

13

它适合放纵的红宝石理念(相对于,例如,Python的严格性):

nil.to_i #=> 0 
"".to_i #=> 0 
"123hello".to_i #=> 123 
"hello".to_i #=> 0 

说实话,我认为这是过于宽松。正如Zabba所述,您可以使用Kernel#Integer(string)进行严格转换。

+3

你不需要使用正则表达式。如果你想在字符串不是完全数字时出错(比如“123hello”),你可以这样做:'Integer(“123hello”)'(引发'ArgumentError')。 – Zabba

+0

+1是的,它似乎过分宽容。很好地放。 – Peter

6

to_i表示“如果可以的话,将我转换为整数”。

如果你想要“如果你非常像整数,给我你的整数值,否则给一个NoMethodError”,然后使用.to_int

还有另外一个问题,询问有关to_ito_int之间的区别,to_sto_str等让我知道,如果你想我帮您找到它。

6

to_i协议说,你必须返回Integer,你不能引发异常。你的两条建议至少违反了其中一条规则。所以,不,这些不仅不会更合乎逻辑,而且会变得无效。

但是,请注意,nil不会回应to_int。如果它确实to_int作出回应,那确实是“不合逻辑的”。

+1

协议说'to_i'必须返回一个整数并不会使这种行为变得合乎逻辑,它只是使其符合规定(假设,即使不合逻辑,也最好符合它)。 –

1

如果你碰巧在Rails的,那么你可以使用try

nil.to_i # => 0 
nil.try :to_i # => nil