I'm not sure that it is a bug.
http://www.ruby-doc.org/ruby-1.9/classes/Enumerable.html#M002713
enum.map {| obj | block } =3D> array
Returns a new array with the results of running block once for every
element in enum.
http://www.ruby-doc.org/ruby-1.9/classes/Enumerable.src/M002713.html
static VALUE
enum_collect(VALUE obj)
{
=A0 =A0 VALUE ary;
=A0 =A0 RETURN_ENUMERATOR(obj, 0, 0);
=A0 =A0 ary =3D rb_ary_new();
=A0 =A0 rb_block_call(obj, id_each, 0, 0, collect_i, ary);
=A0 =A0 return ary;
}
The following is Intransition's methods with some added info.
It looks to me as though two things are happening.
1. Using #map inside #visit combined with using Enumerable#map
=A0 =A0seems to (within #visit) produce the structure of the original arr= ay,
=A0 =A0but with nil values instead of the original values.
=A0 =A0(Changing #map inside #visit to #each gets back the original value= s.)
2. Irrespective of the internal results from #visit, Enumerable#map
=A0 =A0collects the successive results of the block for Enumerable#map
=A0 =A0into a new (flat) array.
=A0 module Enumerable
=A0 =A0 def visit(&block)
puts "#=3D> Enumerable#visit: self=3D0x#{self.object_id}=3D #{self.inspec= t}"
=A0 =A0 =A0 if block_given? then result =3D map do |e| e.visit(&block) en= d
=A0 =A0 =A0 else result =3D to_enum
visit)
=A0 =A0 =A0 end
puts "#=3D> Enumerable#visit: result=3D0x#{result.object_id}=3D #{result.= inspect}"
=A0 =A0 =A0 result
=A0 =A0 end
=A0 end
=A0 class Object
=A0 =A0 def visit(&block) ; block.call(self) ; end
=A0 end
arr =3D [ 10, [ 210 ], 30 ]
it =3D arr.visit
#=3D> Enumerable#visit: self=3D0x13928400=3D [10, [210], 30]
#=3D> Enumerable#visit: result=3D0x13927776=3D #<Enumerator:0x1a90ac0>
puts ; rr =3D it.each{ |x| x+7 }
#=3D> Enumerable#visit: self=3D0x13928400=3D [10, [210], 30]
#=3D> Enumerable#visit: self=3D0x13928416=3D [210]
#=3D> Enumerable#visit: result=3D0x1562576=3D [217]
#=3D> Enumerable#visit: result=3D0x13926848=3D [17, [217], 37]
puts "#=3D> rr=3D0x#{rr.object_id}=3D #{rr.inspect}"
#=3D> rr=3D0x13926848=3D [17, [217], 37]
puts ; rr =3D it.map{ |x| x+7 }
#=3D> Enumerable#visit: self=3D0x13928400=3D [10, [210], 30]
#=3D> Enumerable#visit: self=3D0x13928416=3D [210]
#=3D> Enumerable#visit: result=3D0x1559360=3D [nil]
#=3D> Enumerable#visit: result=3D0x1559840=3D [nil, [nil], nil]
puts "#=3D> rr=3D0x#{rr.object_id}=3D #{rr.inspect}"
#=3D> rr=3D0x1561088=3D [17, 217, 37]
# Note that the last Enumerable#visit result from it.map
# has the same structure as the original nested array
# (albeit with nil values - dunno why at the moment),
# but that the return value of it.map is a flat array
# of the successive results of the block calculation.
Changing:
=A0 =A0 =A0 if block_given? then result =3D map do |e| e.visit(&block) en= d
to:
=A0 =A0 =A0 if block_given? then result =3D each do |e| e.visit(&block) e= nd
gives for it.map:
puts ; rr =3D it.map{ |x| x+7 }
#=3D> Enumerable#visit: self=3D0x14484864=3D [10, [210], 30]
#=3D> Enumerable#visit: self=3D0x14484896=3D [210]
#=3D> Enumerable#visit: result=3D0x14484896=3D [210]
#=3D> Enumerable#visit: result=3D0x14484864=3D [10, [210], 30]
puts "#=3D> rr=3D0x#{rr.object_id}=3D #{rr.inspect}"
#=3D> rr=3D0x1298112=3D [17, 217, 37]