arrays爆炸方法的行为

一些爆炸版的Array方法就像compact!reject!flatten!uniq! 如果没有做出任何更改,则返回nil

 [1,[2]].flatten! # => [1, 2] [1,2].flatten! # => nil [1,[2]].flatten # => [1, 2] [1,2].flatten # => [1, 2] [1,2,nil].compact! # => [1, 2] [1,2].compact! # => nil [1,2,nil].compact # => [1, 2] [1,2].compact # => [1, 2] 

如果他们这样做,就必须有一个理由。 任何想法可能是什么?

bang( ! )方法会修改当前对象,但如果每个文档没有受影响的元素,它们会返回nil 。 如果您因为某种原因需要执行某些操作(如果您修改了相关数组),这将非常有用。

 if array.flatten! puts "Oh yeah... flattened that array!" end 

我总是在印象中说,爆炸版的Array方法只是在他们修改对象的方式上有所不同。

也许这里的问题是,这种印象并不是真正正确的: 根据David A. Black ! 并不意味着该方法改变其接收者; ! 意味着此方法是其他等效方法的“危险”版本 ,它具有相同的名称减去!

现在危险有多种forms( 强调我的 ):

有时,即使在一种方法中,你也会获得不止一种“危险”。 拿String#gsub! 。 此方法更改其接收器:

 str = "David" str.gsub!(/$/, " Black") str # David Black 

它也与gsub (非爆炸)的不同之处在于,如果字符串没有改变, gsub将返回未更改字符串的副本,但是gsub! 返回nil:

 str.gsub(/xyz/, "blah") # David Black str.gsub!(/xyz/, "blah") # nil str # David Black 

的! gsub! 给你一个提醒:它警告你危险,这意味着在你使用这个方法之前,你应该确切地知道它的行为方式。 (一个简单的“ ri String#gsub! ”应该这样做。)

这种“抬头”语义也适用于Array的爆炸方法。