[英]Ruby for loop a trap?
在對Ruby循環的討論中,與每個循環相比, Niklas B.最近談到了循環“不引入新范圍”。 我想看一些人們如何看待這個問題的例子。
好吧,我擴展了一個問題:在Ruby的其他地方我們看到了什么apears做/結束塊分隔符,但實際上里面沒有范圍? 還有什么別的...做...結束?
好的,問題的另一個擴展,是否有辦法用花括號{block}編寫循環?
讓我們通過一個例子說明這一點:
results = []
(1..3).each do |i|
results << lambda { i }
end
p results.map(&:call) # => [1,2,3]
很酷,這是預期的。 現在檢查以下內容:
results = []
for i in 1..3
results << lambda { i }
end
p results.map(&:call) # => [3,3,3]
嗯,發生了什么事? 相信我,這些類型的錯誤是令人討厭的追蹤。 Python或JS開發人員會知道我的意思:)
僅僅這一點是我避免像瘟疫這樣的循環的原因,盡管有更多有利於這一立場的好論據。 正如Ben指出的那樣,使用Enumerable
的正確方法幾乎總是會導致更好的代碼,而不是使用普通的舊的,命令式的for
循環或者有趣的Enumerable#each
。 例如,上面的例子也可以簡潔地寫成
lambdas = 1.upto(3).map { |i| lambda { i } }
p lambdas.map(&:call)
我擴展了一個問題:在Ruby的其他地方我們看到了什么apears做/結束塊分隔符,但實際上里面沒有范圍? 還有什么別的...做...結束?
每個循環結構都可以這樣使用:
while true do
#...
end
until false do
# ...
end
另一方面,我們可以在沒有do
情況下編寫其中的每一個(這顯然是可取的):
for i in 1..3
end
while true
end
until false
end
問題的另一個擴展是,有一種方法可以用花括號{block}來編寫循環
不,那里沒有。 另請注意,術語“塊”在Ruby中具有特殊含義。
首先,我會解釋為什么你不希望使用for
,然后解釋為什么你可能。
你不希望使用的主要原因for
是它的非習慣。 如果您使用each
,您可以輕松地將each
替換為map
或find
或each_with_index
而無需對代碼進行重大更改。 但是沒有for_map
或for_find
或for_with_index
。
另一個原因是,如果你在each
塊中的塊內創建一個變量,並且它之前沒有創建過,那么只要該循環存在,它就會保持存在。 一旦你沒有使用它們就擺脫變量是一件好事。
現在我會提到你可能想要使用for
。 each
循環each
創建一個閉包,如果重復該循環次數過多,那么該循環可能會導致性能問題。 在https://stackoverflow.com/a/10325493/38765中 ,我發布了使用while
循環而不是塊使其變慢。
RUN_COUNT = 10_000_000
FIRST_STRING = "Woooooha"
SECOND_STRING = "Woooooha"
def times_double_equal_sign
RUN_COUNT.times do |i|
FIRST_STRING == SECOND_STRING
end
end
def loop_double_equal_sign
i = 0
while i < RUN_COUNT
FIRST_STRING == SECOND_STRING
i += 1
end
end
times_double_equal_sign
始終持續2.4秒,而loop_double_equal_sign
持續0.2至0.3秒。
在https://stackoverflow.com/a/6475413/38765中 ,我發現執行空循環需要1.9秒,而執行空塊需要5.7秒。
知道你為什么會不希望使用for
,知道你為什么會想用for
,只有當你需要使用后者。 除非你對其他語言懷有懷舊情緒。 :)
好吧,在1.9之前的Ruby中,偶數塊也不完美。 他們並不總是引入新的范圍:
i = 0
results = []
(1..3).each do |i|
results << lambda { i }
end
i = 5
p results.map(&:call) # => [5,5,5]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.