2010-09-18 86 views
15

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] 

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

回答

18

bang(!)方法确实会修改当前对象,但如果每个the documentation没有受影响的元素,它们的确会返回nil。如果出于任何原因,如果您修改了有问题的阵列,则需要执行某些操作,这非常有用。

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

这是一个很好的观点。但是你不能说'return array.flatten!',这对我来说似乎有用,或者是 – artemave 2010-09-18 14:17:56

+0

True。如果这就是你想要的,你会说'return array.flatten'(no bang),它会返回原始数组的平面副本。 – 2010-09-18 14:20:32

+6

这迫使我在我不需要的地方复印。这正是我首先使用压缩版本时遇到的问题。 – artemave 2010-09-18 14:23:12

4

我总是在印象中的Array方法 砰版本是 只有在他们 到位修改对象的方式不同。

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

现在的危险采取多种形式(重点煤矿):

有时你会得到不止一个这样的“危险”,即使在一个爆炸 方法 。以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的爆炸方法。

+2

我也读过这篇文章 - 它没有任何意义。 “危险”的含义至多被确定为反直觉行为的标志。那么,也许呢,他们本来不应该这样做呢? – artemave 2010-09-18 22:46:38

+1

并且'在你使用这个方法之前,你应该明确地知道它的行为方式'显然不是一种红宝石般的方式,通常整个生物系统的惯例自然会导致正确的事情。 – artemave 2010-09-18 22:53:44