[#46807] [ruby-trunk - Bug #7625][Open] Arrayを継承したオブジェクトのcompactがArrayを返す — "mogya@... (Daisuke Furukawa)" <mogya@...>

19 messages 2012/12/26

[#46822] [ruby-trunk - Feature #7639][Open] More freedom for location of comments — "sawa (Tsuyoshi Sawada)" <sawadatsuyoshi@...>

14 messages 2012/12/30

[ruby-dev:46685] [Ruby 1.8 - Bug #7493] ブロックを渡された場合最初の1要素のみを返すEnumeratorに対してnextを送り続けると、2度目にStopIteration例外が発生する

From: "knu (Akinori MUSHA)" <knu@...>
Date: 2012-12-02 13:00:58 UTC
List: ruby-dev #46685
Issue #7493 has been updated by knu (Akinori MUSHA).


1.8では、nextは lib/generator.rb で実装されています。

ブロック(の返り値)を欲するメソッドのEnumeratorをnextで回すというのは、つまり必要なブロックを渡していないわけで、そういう使い方は1.8では想定していませんでした。
つまり、事務的な答えとしては、挙動は不定ですということになります。

ただ、空のブロック({})の評価値がnilになることを考えると、1.9以降のようにnilを返してやるのが自然と言えるでしょうね。
Enumerable#to_a も、内部ではnilを返すブロックで繰り返しています。

直すとしたらこうですが、1.8.7はこの類の修正が入ることはもうないでしょうね。
気になるようであれば、ローカルで当てたりモンキーパッチしてみてください。
一応 ruby_1_8 には入れておきます。

Index: lib/generator.rb
===================================================================
--- lib/generator.rb	(revision 38134)
+++ lib/generator.rb	(working copy)
@@ -69,7 +69,7 @@ class Generator
   def initialize(enum = nil, &block)
     if enum
       @block = proc { |g|
-	enum.each { |x| g.yield x }
+	enum.each { |x| g.yield x; nil }
       }
     else
       @block = block

----------------------------------------
Bug #7493: ブロックを渡された場合最初の1要素のみを返すEnumeratorに対してnextを送り続けると、2度目にStopIteration例外が発生する
https://bugs.ruby-lang.org/issues/7493#change-34315

Author: kachick (Kenichi Kamiya)
Status: Open
Priority: Normal
Assignee: 
Category: 
Target version: Ruby 1.8.7
ruby -v: ruby 1.8.7 (2012-10-12 patchlevel 371) [x86_64-linux]


「ブロック付きで動かした場合、最初に見つかった1要素のみを返すメソッド」からEnumeratorを作ると、
2度目のnextでStopIteration例外を返すようです。
思い至った限りで確認したメソッドは、以下の物です。

* Array#index
* Array#find_index
* Array#rindex
* Enumerable#detect
* Enumerable#find

これは、1.8.7と1.9間の仕様に於ける差異と考えた方が良いのでしょうか?
生成されたEnumeratorに対してto_aを送ると全要素を含むArrayが返る事から、
1.8.7に於いても全要素走査出来る方が自然では無いかと感じました。

# to_aとの差異は、dbussinkの指摘で気づくことが出来ました。
# https://github.com/rubinius/rubinius/pull/2063#issuecomment-10881875

  array = [:a, :b, :c]
  index_enum = array.index
  index_enum.to_a #=> [:a, :b, :c]
  index_enum.next #=> :a
  index_enum.next #=> StopIteration: iteration reached at end


-- 
http://bugs.ruby-lang.org/

In This Thread