我认为许多 Rails 开发人员并不完全理解 memoization 的作用以及它是如何工作的。我已经看到它应用于返回延迟加载集合的方法(如 Sequel 数据集),或应用于不带参数但基于实例变量计算某些东西的方法。在第一种情况下,记忆只是开销,而在第二种情况下,它是令人讨厌且难以追踪的错误的来源。
如果我不会应用记忆
- 返回的值只是计算起来有点贵。它必须非常昂贵,并且不能进一步优化,才能值得记忆。
- 返回的值是或可能是延迟加载的
- 该方法不是一个纯函数,即它保证为相同的参数返回完全相同的值——并且只使用参数来完成它的工作,或者其他纯函数。使用实例变量或调用反过来使用实例变量的方法意味着该方法可以为相同的参数返回不同的结果。
还有其他不适合记忆的情况,例如问题中的那个和上面的答案,但我认为这三个不是那么明显。
最后一项可能是最重要的:memoization 根据方法的参数缓存结果,如果方法看起来像这样,它就不能被 memoized:
def unmemoizable1(name)
"%s was here %s" % name, Time.now.strftime('%Y-%m-%d')
end
def unmemoizable2
find_by_shoe_size(@size)
end
然而,两者都可以被重写以利用记忆(尽管在这两种情况下,由于其他原因显然不应该这样做):
def unmemoizable1(name)
memoizable1(name, Time.now.strftime('%Y-%m-%d'))
end
def memoizable1(name, time)
"#{name} was here #{time}"
end
memoize :memoizable1
def unmemoizable2
memoizable2(@size)
end
def memoizable2(size)
find_by_shoe_size(size)
end
memoize :memoizable2
(假设find_by_shoe_size
没有或依赖于任何副作用)
诀窍是从方法中提取一个纯函数,然后对其应用记忆化。