JRuby (please use github issues at http://bugs.jruby.org)
  1. JRuby (please use github issues at http://bugs.jruby.org)
  2. JRUBY-5839

Enumerable#map is picky about it's internal block arguments in --1.9 mode

    Details

    • Type: Bug Bug
    • Status: Closed Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: JRuby 1.6.1, JRuby 1.6.2
    • Fix Version/s: JRuby 1.6.3
    • Component/s: Core Classes/Modules
    • Labels:
      None
    • Number of attachments :
      0

      Description

      This only occurs in --1.9 mode.

      Observed:
      If #each is overridden on a Hash and yields the (key, value) tuple as expanded arguments, then Enumerable#map only yields the key to the block given to it. If #each yields (key, value) as an array, Enumerable#map yields the key and value.

      Expected:
      I would expect #map to be happy with either argument form, since MRI 1.9 allows either.

      Steps to reproduce:

      class BadHash < Hash
        def each
          super do |k, v|
            yield(k,v)
          end
        end
      end
      
      class GoodHash < Hash
        def each
          super do |k, v|
            yield([k,v])
          end
        end
      end
      
      [BadHash, GoodHash].each do |klass|
        hash = klass.new
        hash['a'] = 'b'
      
        hash.map do |k,v|
          puts "#{klass.name}: #{k} => #{v}"
        end
      end
      

      Results with various jruby/ruby versions:

      $ ruby -v
      jruby 1.6.1 (ruby-1.8.7-p330) (2011-04-12 85838f6) (Java HotSpot(TM) 64-Bit Server VM 1.6.0_24) [darwin-x86_64-java]
      
      $ ruby --1.9 tmp/hash_each.rb 
      BadHash: a => 
      GoodHash: a => b
      
      $ ruby tmp/hash_each.rb 
      BadHash: a => b
      GoodHash: a => b
      
      $ rvm use jruby-1.6.2
      info: Using jruby 1.6.2
      
      $ ruby -v
      jruby 1.6.2 (ruby-1.8.7-p330) (2011-05-23 e2ea975) (Java HotSpot(TM) 64-Bit Server VM 1.6.0_24) [darwin-x86_64-java]
      
      $ ruby --1.9 tmp/hash_each.rb 
      BadHash: a => 
      GoodHash: a => b
      
      $ ruby tmp/hash_each.rb 
      BadHash: a => b
      GoodHash: a => b
      
      $ rvm use ruby-1.9.1
      info: Using ruby 1.9.1 p378
      
      $ ruby -v
      ruby 1.9.1p378 (2010-01-10 revision 26273) [i386-darwin10.4.0]
      
      $ ruby tmp/hash_each.rb 
      BadHash: a => b
      GoodHash: a => b
      
      $ rvm use ruby-1.8.7
      info: Using ruby 1.8.7 p299
      
      $ ruby tmp/hash_each.rb 
      BadHash: a => b
      GoodHash: a => b
      

      This currently affects rack v1.3.0 headers - it overrides #each in HeaderHash, then uses map to convert back to a hash, losing the header values:

      (from https://github.com/rack/rack/blob/1.3.0/lib/rack/utils.rb#L336):

            def each
              super do |k, v|
                yield(k, v.respond_to?(:to_ary) ? v.to_ary.join("\n") : v)
              end
            end
      
            def to_hash
              Hash[*map do |k, v|
                [k, v.respond_to?(:to_ary) ? v.to_ary.join("\n") : v]
              end.flatten]
            end
      

        Issue Links

          Activity

            People

            • Assignee:
              Charles Oliver Nutter
              Reporter:
              Tobias Crawley
            • Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: