Project

General

Profile

Actions

Bug #1107

closed

lack consistency in hash iteration

Added by mame (Yusuke Endoh) over 16 years ago. Updated about 14 years ago.

Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
Backport:
[ruby-dev:37910]

Description

=begin
遠藤です。

[ruby-core:21812] で調べていて気が付いたことですが、

$ ./ruby -e 'h = {0 => nil}; i = 1; h.each_key { h[i] = nil; i += 1 }'

は停止し、

$ ./ruby -e 'h = {0 => nil, 1 => nil}; i = 2; h.each_key { h[i] = nil; i += 1 }'

は無限ループになります。
直感的にはどちらも無限ループになると思いました。

特に反対がなければ、以下のパッチをコミットしようと思います。

Index: st.c

--- st.c (revision 22051)
+++ st.c (working copy)
@@ -653,6 +653,7 @@
do {
end = ptr->fore == table->head;
retval = (*func)(ptr->key, ptr->record, arg);

  •  end = end && (ptr->fore == table->head);
     switch (retval) {
       case ST_CHECK:	/* check if hash is modified during iteration */
     i = ptr->hash % table->num_bins;
    

Index: test/ruby/test_hash.rb

--- test/ruby/test_hash.rb (revision 22051)
+++ test/ruby/test_hash.rb (working copy)
@@ -849,4 +849,30 @@
def test_hash_hash
assert_equal({0=>2,11=>1}.hash, {11=>1,0=>2}.hash)
end
+

  • def test_iteration_order
  • h = {1=>nil,3=>nil,2=>nil,4=>nil}
  • assert_equal([1, 3, 2, 4], h.each_key.to_a)
  • h.each_key {|k| h[k + 10] = nil if h.size < 8 }
  • assert_equal([1, 3, 2, 4, 11, 13, 12, 14], h.each_key.to_a)
  • h = {0=>nil}
  • i = 1
  • h.each_key do |k|
  •  break if h.size == 5
    
  •  h[i] = nil
    
  •  i += 1
    
  • end
  • assert_equal({0=>nil,1=>nil,2=>nil,3=>nil,4=>nil}, h)
  • h = {0=>nil,1=>nil}
  • i = 2
  • h.each_key do |k|
  •  break if h.size == 5
    
  •  h[i] = nil
    
  •  i += 1
    
  • end
  • assert_equal({0=>nil,1=>nil,2=>nil,3=>nil,4=>nil}, h)
  • end
    end

--
Yusuke ENDOH
=end

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0