Rubyループの議論で、Niklas B.は最近、各ループと比較して、「新しいスコープを導入しない」forループについて話しました。これをどのように感じているかの例をいくつか見てみたいと思います。
OK、質問を拡張します。Rubyの他のどこで、ブロック区切り文字の表示/終了を確認できますが、実際には内部にスコープはありませんか?for ... do ... end以外に何かありますか?
OK、質問のもう1つの拡張ですが、中括弧{ブロック}を使用してforループを作成する方法はありますか?
例でポイントを説明しましょう:
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 が正しく指摘したように、適切なメソッド from を使用すると、Enumerable
ほとんどの場合、単純な古い命令型for
ループや手の込んだを使用するよりも優れたコードになりますEnumerable#each
。たとえば、上記の例は次のように簡潔に書くこともできます。
lambdas = 1.upto(3).map { |i| lambda { i } }
p lambdas.map(&:call)
質問を拡張します。Ruby の他のどこで、apears がブロック区切り文字を実行/終了するかを確認できますが、実際には内部にスコープはありませんか? for ... do ... end 以外に何かありますか?
ループ構造はすべて、次のように使用できます。
while true do
#...
end
until false do
# ...
end
一方、これらのすべてを なしで書くことができますdo
(これは明らかに好ましいです):
for i in 1..3
end
while true
end
until false
end
質問のもう 1 つの拡張は、中かっこ { ブロック } を使用して for ループを記述する方法はありますか
いいえ、ありません。また、「ブロック」という用語は、Ruby では特別な意味を持つことに注意してください。
まず、使用したくない理由をfor
説明し、次に使用する理由を説明します。
使用したくない主な理由for
は、それが慣用的ではないということです。を使用すると、コードを大幅に変更することなく、簡単にaまたはaまたはaneach
に置き換えることができます。しかし、またははありません。each
map
find
each_with_index
for_map
for_find
for_with_index
もう1つの理由は、内のブロック内each
に変数を作成し、それが事前に作成されていない場合、そのループが存在する間だけ存在し続けるということです。変数を使用しなくなったら、変数を取り除くのは良いことです。
次に、を使用する理由について説明しますfor
。each
ループごとにクロージャを作成します。そのループを何度も繰り返すと、そのループによってパフォーマンスの問題が発生する可能性があります。https://stackoverflow.com/a/10325493/38765while
で、ブロックではなくループを使用すると速度が低下することを投稿しました。
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]