尝试跟随pragpub的元编程截屏,并因为自截屏视频发布以来Ruby的变化而遇到了一些问题。
很难解释没有代码的问题,所以这就是:
class Discounter
def discount(*skus)
expensive_discount_calculation(*skus)
end
private
def expensive_discount_calculation(*skus)
puts "Expensive calculation for #{skus.inspect}"
skus.inject {|m, n| m + n }
end
end
def memoize(obj, method)
ghost = class << obj; self; end
ghost.class_eval do
define_method(method) do |*args|
memory ||= {}
memory.has_key?(args) ? memory[args] : memory[args] = super(*args)
end
end
end
d = Discounter.new
memoize(d, :discount)
puts d.discount(1,2,3)
puts d.discount(1,2,3)
puts d.discount(2,3,4)
puts d.discount(2,3,4)
问题:方法memorize中的局部变量只应更改(通过从Discounter#折扣中获取返回值),如果它传递的参数不同于以前的参数。
例如,我希望运行上面代码的输出看起来像:
Expensive calculation for [1, 2, 3]
6
6
Expensive calculation for [2, 3, 4]
9
9
但这是实际输出:
Expensive calculation for [1, 2, 3]
6
Expensive calculation for [1, 2, 3]
6
Expensive calculation for [2, 3, 4]
9
Expensive calculation for [2, 3, 4]
9
为什么本地变量不会在调用中持续存在?为了使这段代码有用,我错过了什么?
由于
答案 0 :(得分:3)
如果在块内定义局部变量,则在到达块的末尾时它将消失。
要实现所需的生命周期,您需要在块之前定义memory
变量:
def memoize(obj, method)
memory = {}
ghost = class << obj; self; end
ghost.class_eval do
define_method(method) do |*args|
memory.has_key?(args) ? memory[args] : memory[args] = super(*args)
end
end
end