Ruby 方法调用中是否有记忆约定?
我希望避免在方法调用中重新评估值。直到现在,我一直在这样做:Ruby 方法调用中是否有记忆约定?,ruby,coding-style,memoization,Ruby,Coding Style,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 ||= 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
- 在前面加下划线是一个好习惯吗
- 对于记忆化/非记忆化的方法对是否有其他约定
- 是否有一些惯例来记忆多行方法
- 我会这样做:
def filesize
@filesize ||= calculate_filesize
end
private
def calculate_filesize
# ...
end
因此,我会用不同的方法命名,因为我认为它更有意义。我通常使用第一个示例中的
begin,end
,但是如果有更多的代码,我只看变量是否存在,不需要为此创建另一个方法
def some_method
return @some_method if @some_method
# lot's of code
@some_method
end
我认为还有一种方式,更具Java风格 首先,您应该实现注释,如“”和“” 然后,您应该添加类似于_cacheable的注释,该注释将告诉方法它应该返回实例变量,如果它为null,则应该通过调用方法来计算它,这样您的代码将更加清晰:
_cacheable
def some_method
# do_some_work
end
我也不喜欢爆炸。我用
def some_method
@some_method_memo ||= some_method_eval
end
private
def some_method_eval
# lot's of code
end
这里的eval
是评估的缩写。我喜欢它的阅读方式,也喜欢它使公共界面简洁
我鄙视依赖下划线作为区分标记的约定:它们都容易出错,并且要求我记住YAMC(另一个毫无意义的约定)。Ada语言是为安全关键应用程序设计的,不允许使用前导、尾随或多个下划线。好主意。我通常会这样回答或:
def filesize() @filesize ||=
calculate_filesize
end
顺便说一句:
我经常使用这种记忆技巧:
def filesize() @_memo[:filesize] ||=
calculate_filesize
end
这将允许您稍后用一个简单的@\u memo.clear
清除所有已记忆的变量。@|u memo变量的初始化应如下所示Hash.new{h,k|h[k]=Hash.new}
。
它为您提供了使用ActiveSupport::Memoize和类似的元编程技术的许多优点。我使用gem,它让您可以轻松地记忆一个方法,而无需更改原始方法或创建两个方法
例如,与其使用两种方法,file\u size
和calculate\u file\u size
,还不如自己使用一个实例变量来实现记忆:
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
每个已记忆的函数都有一种刷新现有值的方法
object.file_size # returns the memoized value
object.file_size(true) # bypasses the memoized value and rememoizes it
因此,调用object.file\u size(true)
将等同于调用object.calculate\u file\u size
…,这是行不通的。您需要将return
放在def的第一行前面。我唯一不喜欢这种方法的是,编码人员需要编辑方法,以便将@some_method
变量分配到其中的某个位置,从而在方法的逻辑中混合了记忆逻辑。我认为您太苛刻了,因为这首先取决于方法的作用。例如,我有时在rails助手中使用它,这非常有意义。更不用说模块内部的private关键字一开始就不能很好地工作。另外,由于你也对AGI投了否决票,所以仅仅因为你不完全同意他们就对所有答案投否决票是不好的。相关:使用Rails的classActiveSupport::Memoize
似乎很好:。你希望得到什么样的答案?Vise和Agis都提出了良好的约定。另外,您的第二块代码是一个常见的约定。我喜欢| |=begin…end
。我觉得很优雅,由你决定__一些方法,计算一些方法,计算一些方法,计算一些方法,一些方法,一些方法,一些方法代码注意:在什么时候和为什么要使用感叹号。我认为这有点超出了公约的目的,但值得考虑。再次稍微偏离了这里的相关内容,但有价值,所以尽管说“我没有修改对象”是可以的,但说“我不喜欢爆炸”是避免它的一个不太明显的理由。我不喜欢在方法名称前放这么多字符,以便将其标记为未经修改的版本。为什么?它在语义上是有意义的,并且非常明显它在做什么。对更少角色的盲目追求让你忽略了最佳答案。+1。这些名称准确地描述了函数正在做的事情,包括它们的预期性能。尽管赏金去了其他地方,但我还是接受这个名称,因为它更符合其他ruby约定。请投票支持最后的(积极的)长篇大论。烧掉所有YAMC:)