在方法调用中是否存在memoization约定?
我想避免重新评估方法调用中的值。 直到现在,我这样做:
def some_method @some_method ||= begin # lot's of code end end
但它最终很难看。 在某些代码中,我看到如下内容:
def some_method @some_method ||= some_method! end private def some_method! # lot's of code end
我不喜欢最后的爆炸声( !
),所以我想出了这个:
def some_method @some_method ||= _some_method end private def _some_method # lot's of code end
- 是否以下划线作为一个好的约定?
- memoized / non-memoized对方法是否有其他约定?
- 是否有一些惯例来记忆多行方法?
我会这样做:
def filesize @filesize ||= calculate_filesize end private def calculate_filesize # ... end
所以我只是以不同的方式命名方法,因为我觉得它更有意义。
还有一种方法,我认为更多Java风格。
首先,您应该实现注释,例如“ Ruby中的Java样式注释 ”和“ 如何 在Ruby 中模拟类似Java的注释? ”。
然后你应该添加像_cacheable这样的注释,它会告诉它应该返回实例变量的方法,如果它是null,它应该通过调用方法来计算它,所以你的代码会更清楚:
_cacheable def some_method # do_some_work end
我使用memoist gem,它可以让你轻松地记忆方法,而无需改变原始方法或创建两种方法。
因此,例如,不要使用两个方法file_size
和calculate_file_size
,而必须使用实例变量自己实现memoization:
def file_size @file_size ||= calculate_file_size end def calculate_file_size # code to calculate the file size end
你可以这样做:
def file_size # code to calculate the file size end memoize :file_size
每个memoized函数都有一种刷新现有值的方法。
object.file_size # returns the memoized value object.file_size(true) # bypasses the memoized value and rememoizes it
所以调用object.file_size(true)
将等同于调用object.calculate_file_size
…
我通常按照你的第一个例子使用begin, end
,但如果有更多的代码,我只看看变量是否存在,不需要为此创建另一个方法。
def some_method return @some_method if @some_method # lot's of code @some_method end
我也不喜欢爆炸。 我用
def some_method @some_method_memo ||= some_method_eval end private def some_method_eval # lot's of code end
这里eval
是evaluation
简写。 我喜欢这种读取的方式,并且它使公共界面简洁。
我鄙视依靠下划线作为区别标记的惯例:它们都容易出错,需要我记得YAMC(又一个毫无意义的惯例)。 Ada语言专为安全关键型应用程序而设计,不允许使用前导,尾随或多个下划线。 好主意。
我通常在Agis的答案或者:
def filesize() @filesize ||= calculate_filesize end
BTW:
我经常使用这种记忆技术:
def filesize() @_memo[:filesize] ||= calculate_filesize end
这将允许您稍后使用一个简单的@_memo.clear
清除所有已记忆的变量。 @_memo变量应该像这个Hash.new { |h, k| h[k] = Hash.new }
一样初始化 Hash.new { |h, k| h[k] = Hash.new }
。 它为您提供了许多使用ActiveSupport :: Memoize和类似元编程技术的冒险,这些技术可能要慢得多 。