16

Rubyループの議論で、Niklas B.は最近、各ループと比較して、「新しいスコープを導入しない」forループについて話しました。これをどのように感じているかの例をいくつか見てみたいと思います。

OK、質問を拡張します。Rubyの他のどこで、ブロック区切り文字の表示/終了を確認できますが、実際には内部にスコープはありませんか?for ... do ... end以外に何かありますか?

OK、質問のもう1つの拡張ですが、中括弧{ブロック}を使用してforループを作成する方法はありますか?

4

3 に答える 3

14

例でポイントを説明しましょう:

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 では特別な意味を持つことに注意してください。

于 2012-05-01T11:29:17.827 に答える
3

まず、使用したくない理由をfor説明し、次に使用する理由を説明します。

使用したくない主な理由forは、それが慣用的ではないということです。を使用すると、コードを大幅に変更することなく、簡単にaまたはaまたはaneachに置き換えることができます。しかし、またははありません。eachmapfindeach_with_indexfor_mapfor_findfor_with_index

もう1つの理由は、内のブロック内eachに変数を作成し、それが事前に作成されていない場合、そのループが存在する間だけ存在し続けるということです。変数を使用しなくなったら、変数を取り除くのは良いことです。

次に、を使用する理由について説明しますforeachループごとにクロージャを作成します。そのループを何度も繰り返すと、そのループによってパフォーマンスの問題が発生する可能性があります。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必要な場合にのみ後者を使用してください。他の言語に懐かしさを感じない限り。:)

于 2012-05-01T23:33:16.690 に答える
1

まあ、1.9より前のRubyではブロックでさえ完璧ではありません。彼らは常に新しいスコープを導入するとは限りません:

i = 0
results = []
(1..3).each do |i|
  results << lambda { i }
end
i = 5
p results.map(&:call)  # => [5,5,5]
于 2012-05-01T13:56:21.230 に答える