Module#prepend
在紅寶石2+的溶液中加入特別是在因爲它可以(除了別的以外)作爲一個方法組合子/裝飾蟒蛇。這樣,你實際上不需要訪問方法本身,你可以重寫它。
class Module
def memoize(meth)
prepend(Module.new do
memo = {}
define_method(meth) do |*args, &blk|
memo[[self, *args, blk]] ||= super(*args, &blk)
end
end)
end
end
class Integer
memoize def fib
raise ArgumentError if self < 0
return self if self < 2
pred.fib + pred.pred.fib
end
end
require 'benchmark'
puts Benchmark.measure { p 42.fib }
在舊版本的紅寶石(1.9或以上),你將不得不做這樣的事情:
class Module
def memoize(meth)
memo = {}
old_meth = instance_method(meth)
define_method(meth) do |*args, &blk|
memo[[self, *args, blk]] ||= old_meth.bind(self).(*args, &blk)
end
end
end
此外,def
評估到Symbol
表示方法的名字被定義爲在Ruby中2.2增加,因此,在舊版本中,你不得不這樣做,而不是:
class Integer
def fib
raise ArgumentError if self < 0
return self if self < 2
pred.fib + pred.pred.fib
end
memoize :fib
end
我們可以作爲一個耙用於其使用這種伎倆方法,雖然,以使其memoize的下一個方法被定義:
class Module
def memoize(meth=nil)
return @__memoize_next_method__ = true unless meth
memo = {}
old_meth = instance_method(meth)
define_method(meth) do |*args, &blk|
memo[[self, *args, blk]] ||= old_meth.bind(self).(*args, &blk)
end
end
def method_added(meth)
return if @__recursing__
@__recursing__ = true # protect against infinite recursion
if @__memoize_next_method__
memoize(meth)
@__memoize_next_method__ = nil
end
@recursing = nil
end
end
class Integer
memoize
def fib
raise ArgumentError if self < 0
return self if self < 2
pred.fib + pred.pred.fib
end
end
結帳[4種簡單記憶化模式在紅寶石(http://www.justinweiss.com/articles/4-simple-memoization-patterns -in-ruby-and-one-gem /)使用'@ instance_variable' –
我很困惑。你顯示Ruby(?)代碼來做一件事,然後問如何在Ruby中做到這一點? –
@JonathonReinhart它是函數與方法 –