新手问题 不懂用了 array dup 和 map 的代码里面有个出乎意料的结果

u4crella · 2019年12月27日 · 最后由 u4crella 回复于 2019年12月27日 · 2003 次阅读

在下面代码使用 array 的 clone 或者 dup,然后用 array.map 的时候,发现了我所不理解的地方,为什么 blist 最后还是会被修改呢,请指点,谢谢。

class Pata
  attr_accessor :d
  def initialize(x)
    @d = x
  end
end

def func(blist)
  clist = blist.dup
  puts 'enter func'
  puts 'blist=', blist.inspect, '----'
  puts 'clist=', clist.inspect, '----', '#####'
  (1 .. 2).each do |n|
    clist = clist.map do |m|
      if n.even?
    m.d += 2
      else
    m.d += 1
      end
      m
    end
  end
  puts 'before exit :: func'
  puts 'blist=', blist.inspect, '----'
  puts 'clist=', clist.inspect, '----', '#####'
  return clist
end

list1 = [ Pata.new(4),  Pata.new(5), Pata.new(7) ]
list2 = func(list1)
puts 'return to main from func'
puts 'list1=', list1.inspect, '----'
puts 'list2=', list2.inspect, '----'

__END__
环境
ruby 2.6.4p104 (2019-08-28 revision 67798) [x86_64-msys]


结果

$ ruby test_map.rb
enter func
blist=
[#<Pata:0x00000006004896c0 @d=4>, #<Pata:0x0000000600489698 @d=5>, #<Pata:0x0000000600489670 @d=7>]
----
clist=
[#<Pata:0x00000006004896c0 @d=4>, #<Pata:0x0000000600489698 @d=5>, #<Pata:0x0000000600489670 @d=7>]
----
#####
before exit :: func
blist=
[#<Pata:0x00000006004896c0 @d=7>, #<Pata:0x0000000600489698 @d=8>, #<Pata:0x0000000600489670 @d=10>]
----
clist=
[#<Pata:0x00000006004896c0 @d=7>, #<Pata:0x0000000600489698 @d=8>, #<Pata:0x0000000600489670 @d=10>]
----
#####
return to main from func
list1=
[#<Pata:0x00000006004896c0 @d=7>, #<Pata:0x0000000600489698 @d=8>, #<Pata:0x0000000600489670 @d=10>]
----
list2=
[#<Pata:0x00000006004896c0 @d=7>, #<Pata:0x0000000600489698 @d=8>, #<Pata:0x0000000600489670 @d=10>]
----

现在有点明白了,map 抛出的 Enumerator 也只是对元素的引用,所以在 map 里面修改 Enumerator 的每个元素会影响到 map 以外对应的实际的元素。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号