Project

General

Profile

Actions

Bug #992

closed

Hash becomes Array for no apparent reason.

Added by loqi (Loqi Tamaroon) about 15 years ago. Updated almost 13 years ago.

Status:
Rejected
Assignee:
-
Target version:
ruby -v:
[ruby-core:21226]

Description

=begin

Using Ruby 1.8.6 (2008-03-03 patchlevel 114) [universal-darwin9.0]

on Mac OS X 10.5.5

def is_this_a_ruby_bug?
orig_hash = { :a=>[:x], :b=>[:x] }
orig_hash.inject({}) do | flipped_hash, (symbol_a_or_b, array_x) |
array_x.each do |symbol_x|
(flipped_hash[symbol_x] ||= []) << symbol_a_or_b # (~1)
flipped_hash # (~2)
end # (~3)

flipped_hash # (~4)

end
end
is_this_a_ruby_bug?

The above method is supposed to return { :x => [:a, :b] } . Instead, it exhibits

bizarre behavior. On the first iteration of the inner loop, line (~2) somehow causes

flipped_hash to be recast from Hash {:x=>[:a]} to Array [:x] . This causes (~1) to

raise a "Symbol as array index (TypeError)" exception on the second iteration of

array_x.each , because flipped_hash has accedentally become an Array. A workaround

is to uncomment (~4), which curiously is OUTSIDE the inner loop where the exception

would've occured. The effect is that the 'end' at (~3) no longer terminates the inner

loop and (~4) is now executed with each iteration of array_x.each as if it were above

(~3). Somehow this fixes the problem, and the method returns the expected result.

=end

Actions #1

Updated by shyouhei (Shyouhei Urabe) about 15 years ago

  • Status changed from Open to Rejected

=begin
No it isn't. Your "workaround" is the canonical way. See whatever documentation you like that describes inject method.
=end

Actions #2

Updated by mernen (Daniel Luz) about 15 years ago

=begin
Since Enumerable#each ignores the return value of the block, (~2) is a no-op. #each returns the original object (in this case, array_x), and as such you're passing the second iteration of #inject array_x, not flipped_hash. (~4) is the correct position to return a value here.
=end

Actions #3

Updated by loqi (Loqi Tamaroon) about 15 years ago

=begin
Hey thanks Daniel. I missed that detail about #each . I'm new to Ruby.

=end

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0