奇怪的红宝石行为与常数

时间:2013-05-18 17:08:20

标签: ruby constants behavior

有人可以解释一下,为什么我的原始常数LIST从一开始就被操纵了?我认为常数可能只是一次初始化。我想将操作存储在一个新数组(new_list)中而不影响原始数组(LIST)。

$ned = "foo"
$med = ""

print LIST = [:nrd, :mrd_y] # -> [:nrd, :mrd_y]


list = LIST

new_list = list.delete_if { |element|
  case element
  when :nrd then $ned.empty?
  when :mrd_y then $ned.empty? || $med.empty?
  end
}

print new_list # -> [:nrd]

print LIST # -> [:nrd] instead of [:nrd, :mrd_y]

1 个答案:

答案 0 :(得分:2)

  

Array#delete_if - >删除块评估为true的self的每个元素。

$ned = "foo"
$med = ""

LIST = [:nrd, :mrd_y]
p LIST.object_id #=> 84053120
list = LIST
p LIST.object_id #=> 84053120
new_list = list.delete_if { |element|
  case element
  when :nrd then $ned.empty?
  when :mrd_y then $ned.empty? || $med.empty?
  end
}

Listlist持有相同的Array对象,如object_id所述。因此,对于块true中的每个delete_if评估,都会从84053120引用的对象中删除项目。由LISTlist保留。所以你可以使用下面的内容:

$ned = "foo"
$med = ""

LIST = [:nrd, :mrd_y] 
list = LIST
new_list = list.dup.delete_if { |element|
  case element
  when :nrd then $ned.empty?
  when :mrd_y then $ned.empty? || $med.empty?
  end
}

p new_list #=>[:nrd]
p LIST #=>[:nrd, :mrd_y]
  

或(更好的方法使用Array#reject),

$ned = "foo"
$med = ""

list = [:nrd, :mrd_y]  
new_list = list.reject { |element|
  case element
  when :nrd then $ned.empty?
  when :mrd_y then $ned.empty? || $med.empty?
  end
}
p new_list #=>[:nrd]
p list #=>[:nrd, :mrd_y]