(我之前提问的后续问题,Ruby: how can I copy a variable without pointing to the same object?)
我正在编写一个简单的Ruby程序,以便在.svg文件中进行一些替换。第一步是从文件中提取信息并将其放入数组中。为了防止每次调用此函数时都从磁盘读取文件,我正在尝试使用memoize设计模式 - 在第一次调用后的每次调用时使用缓存结果。
为此,我正在使用一个在函数之前定义的全局变量。但即使我.dup
在返回局部变量之前该变量为本地变量,调用此变量的函数仍在修改全局变量。
这是我的实际代码:
#memoize to keep from having to read original file on each pass
$svg_filedata_cache = [] #the global variable
def svg_filedata(filename)
if $svg_filedata_cache.empty?
File.open(filename, "r"){|f| $svg_filedata_cache = f.readlines}
end
svg_filedata_cache = $svg_filedata_cache.dup #try to copy it
return svg_filedata_cache #SHOULD point to a different object (but doesn't)
end
两个问题(回答其中一个或两个):
.dup
复制它?答案 0 :(得分:9)
修改duped数组不会影响原始数据。但是,对数组内部字符串的修改将全局可见,因为全局数组和duped数组仍包含对相同字符串的引用(dup不执行深层复制)。
因此要么执行深层复制(svg_filedata_cache = $svg_filedata_cache.map {|line| line.dup}
),要么只是避免对字符串进行变更操作。
答案 1 :(得分:6)
稍微增强代码:
$svg_filedata_cache = [] #the global variable
def svg_filedata(filename)
# Use ||= for memoiziation
$svg_filedata_cache ||= File.open(filename, "r"){|f| $svg_filedata_cache = f.readlines}
$svg_filedata_cache.dup #shallow copying
end
更新:一般来说,进行深度复制的一个简单方法是:
def deep_copy(obj)
Marshal.load(Marshal.dump(obj))
end
答案 2 :(得分:2)
全局可能没有被修改,但它和你的.dup引用的元素正在改变。为了使它成为更规范的ruby,摆脱全局,使用类,并在initialize
函数中读取文件。 (构造函数。)使用@v。