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

!最後の強打 ( )が気に入らないので、次のように考えました。

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

もう 1 つ方法があります。もっと Java スタイルだと思います。

まず最初に、 「 Ruby での Java スタイルのアノテーション」や「 Rubyで Java のようなアノテーションをシミュレートするにはどうすればよいですか?」のようなアノテーションを実装する必要があります。

次に、インスタンス変数を返す必要があることをメソッドに伝える _cacheable などの注釈を追加する必要があります。それが null の場合は、メソッドを呼び出して計算する必要があるため、コードがより明確になります。

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

memoist gemを使用すると、元のメソッドを変更したり 2 つのメソッドを作成したりすることなく、メソッドを簡単にメモ化できます。

したがって、たとえば、 と の 2 つのメソッドを使用する代わりに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 

これevalはの省略形ですevaluation。私はこれが読む方法が好きで、またそれがパブリックインターフェースを簡潔にすることも好きです。

アンダースコアを区別マークとして使用する規則は軽蔑します。どちらもエラーが発生しやすく、YAMC(さらに別の無意味な規則)を覚えておく必要があります。セーフティクリティカルなアプリケーション向けに設計されたAda言語では、先頭、末尾、または複数のアンダースコアを使用できません。良いアイデア。

于 2012-10-18T05:12:53.103 に答える
0

私は通常、Agisの回答のように行うか、次のようにします。

def filesize() @filesize ||=
  calculate_filesize
end

ところで:

私はよくこのメモ化手法を使用します。

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

これにより、メモ化されたすべての変数を後で 1 つの単純な でクリアできます@_memo.clear。@_memo 変数は、次のように初期化する必要がありますHash.new { |h, k| h[k] = Hash.new }。ActiveSupport::Memoize や同様のメタ プログラム手法を使用する利点の多くが得られますが、これははるかに遅くなる可能性があります

于 2012-10-22T10:49:20.797 に答える