15

我想避免重新评估方法调用中的值。直到现在,我正在这样做:

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

我不喜欢!结尾的 bang ( ),所以我想出了这个:

def some_method
  @some_method ||= _some_method
end

private

def _some_method
  # lot's of code
end
  • 在前面加上下划线是一个好的约定吗?
  • 对于记忆/非记忆的方法对是否有其他约定?
  • 是否有一些约定来记忆多行方法?
4

6 回答 6

27

我会这样做:

def filesize
  @filesize ||= calculate_filesize
end

private

def calculate_filesize
  # ...
end

所以我只是以不同的方式命名该方法,因为我认为它更有意义。

于 2012-10-10T12:05:17.187 回答
8

我认为还有另一种方式,更多Java风格。

首先你应该实现注解,比如“ Ruby 中的Java 风格的注解”和“如何在Ruby 中模拟Java 风格的注解? ”。

然后你应该添加像 _cacheable 这样的注释,它将告诉方法它应该返回实例变量,如果它是 null 它应该通过调用方法来计算它,这样你的代码会更清晰:

_cacheable
def some_method
   # do_some_work
end
于 2012-10-15T03:45:36.673 回答
4

我使用memoist gem,它可以让您轻松地记住一个方法,而无需更改原始方法或创建两个方法。

因此,例如,不必使用两个方法file_sizecalculate_file_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_size(true)就相当于调用object.calculate_file_size......

于 2013-09-19T18:19:21.827 回答
2

我通常begin, end按​​照您的第一个示例使用,但如果有更多代码,我只需查看变量是否存在,无需为此创建另一个方法。

def some_method
  return @some_method if @some_method
  # lot's of code
  @some_method
end
于 2012-10-10T12:23:10.257 回答
1

我也不喜欢砰的一声。我用

def some_method 
  @some_method_memo ||= some_method_eval 
end 

private 

def some_method_eval
  # lot's of code 
end 

这里evalevaluation. 我喜欢它的阅读方式,也喜欢它使公共界面简洁。

我鄙视依赖下划线作为区分标记的约定:它们都容易出错并且要求我记住 YAMC(又一个无意义的约定)。Ada 语言专为安全关键型应用程序而设计,不允许前导、尾随或多个下划线。好主意。

于 2012-10-18T05:12:53.103 回答
0

我通常会像在Agis回答中那样做,或者:

def filesize() @filesize ||=
  calculate_filesize
end

顺便提一句:

我经常使用这种记忆技术:

def filesize() @_memo[:filesize] ||=
  calculate_filesize
end

这将允许您稍后使用一个简单的@_memo.clear. @_memo 变量应该像这样初始化Hash.new { |h, k| h[k] = Hash.new }。它为您提供了使用 ActiveSupport::Memoize 和类似的元编程技术的许多冒险,这些技术可能要慢得多

于 2012-10-22T10:49:20.797 回答