我想避免在方法调用中重新评估值。直到现在,我这样做:
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
答案 0 :(得分:24)
我会这样做:
def filesize
@filesize ||= calculate_filesize
end
private
def calculate_filesize
# ...
end
所以我只是以不同的方式命名方法,因为我觉得它更有意义。
答案 1 :(得分:9)
我认为还有一种方式,更多Java风格。
首先,您应该实施注释,例如“Java-style annotations in Ruby”和“How to simulate Java-like annotations in Ruby?”。
然后你应该添加像_cacheable这样的注释,它会告诉它应该返回实例变量的方法,如果它是null,它应该通过调用方法来计算它,所以你的代码会更清楚:
_cacheable
def some_method
# do_some_work
end
答案 2 :(得分:5)
我使用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
...
答案 3 :(得分:3)
我通常根据你的第一个例子使用begin, end
,但如果有更多的代码,我只看看变量是否存在,不需要为此创建另一个方法。
def some_method
return @some_method if @some_method
# lot's of code
@some_method
end
答案 4 :(得分:2)
我也不喜欢爆炸。我用
def some_method
@some_method_memo ||= some_method_eval
end
private
def some_method_eval
# lot's of code
end
此处eval
是evaluation
的简写。我喜欢这种读取的方式,并且它使公共界面简洁。
我鄙视依赖下划线作为区别标记的惯例:它们都容易出错,需要我记住YAMC(又一个毫无意义的惯例)。 Ada语言专为安全关键型应用程序而设计,不允许使用前导,尾随或多个下划线。好主意。
答案 5 :(得分:0)
我通常会在Agis回答或
中执行此操作def filesize() @filesize ||=
calculate_filesize
end
顺便说一句:
我经常使用这种记忆技术:
def filesize() @_memo[:filesize] ||=
calculate_filesize
end
这将允许您稍后使用一个简单的@_memo.clear
清除所有已记忆的变量。应该像这样Hash.new { |h, k| h[k] = Hash.new }
初始化@_memo变量。
它为您提供了许多使用ActiveSupport :: Memoize以及might be much slower的类似元编程技术的尝试。