From: "shugo (Shugo Maeda)" Date: 2012-03-19T16:57:19+09:00 Subject: [ruby-core:43463] [ruby-trunk - Bug #6155] Enumerable::Lazy#flat_map raises an exception when an element does not respond to #each Issue #6155 has been updated by shugo (Shugo Maeda). I'll fix lazy flat_map respecting Matz's opinion, but let me clarify one point. dkubb (Dan Kubb) wrote: > > > [1, 2, 3].flat_map { |n| n }.to_a > > > > I doubt that this behavior of Enumerable#flat_map is reasonable. > > I was writing rubyspec for Enumerable::Lazy#flat_map had the same behaviour as Enumerable#flat_map (besides the obvious differences in return value). Here is what I was using as a basis: https://github.com/rubyspec/rubyspec/blob/master/core/enumerable/shared/collect_concat.rb > > The last example doesn't apply, since it should raise an exception when no block is provided (according to the current implementation), but the first 3 specs fail because they have mixed data, they are equivalent to: > > [1, [2, 3], [4, [5, 6]], {:foo => :bar}].lazy.flat_map { |e| e }.to_a > [1, [], 2].lazy.flat_map { |e| e }.to_a > [[:foo], Object.new.tap { |o| class << o; def to_a() end end }].lazy.flat_map { |e| e }.to_a > > All of the above examples work when the enumerable is not lazy. Why the last example defines to_a? flat_map doesn't call to_a, but to_ary. p [Object.new.tap { |o| class << o def to_a; [:to_a] end end }].flat_map { |e| e } #=> [#] p [Object.new.tap { |o| class << o def to_ary; [:to_ary] end end }].flat_map { |e| e } #=> [:to_ary] ---------------------------------------- Bug #6155: Enumerable::Lazy#flat_map raises an exception when an element does not respond to #each https://bugs.ruby-lang.org/issues/6155#change-24932 Author: dkubb (Dan Kubb) Status: Assigned Priority: Normal Assignee: shugo (Shugo Maeda) Category: core Target version: 2.0.0 ruby -v: ruby 2.0.0dev (2012-03-15 trunk 35028) [x86_64-darwin11.3.0] The following statement will raise "NoMethodError: undefined method `each' for 1:Fixnum": [1, 2, 3].lazy.flat_map { |n| n }.to_a It appears as if Enumerable::Lazy#flat_map is calling #each on every element, regardless of whether it can work or not. As a reference, the equivalent statement using Enumerable#flat_map works: [1, 2, 3].flat_map { |n| n }.to_a -- http://bugs.ruby-lang.org/