変数に何かを代入したいが、最初に代入したい値を計算しなければならない場合に、これを時々使用します。これにより、コードが少し整頓されます。ユーザーの好みだと思います。基本的にあなたはこう言っています: foo に何かを割り当てていますが、必要な値を取得するには、まずいくつかのことを行う必要があります。メモ化を行うときに特に便利です。
if @cache.nil?
do_something!
@cache = read_value
end
できるよ
@cache ||= begin
do_something!
read_value
end
ここで利用しているのは、Ruby インタープリターにはスタックがあり、各式は通常、スタックに何かをプッシュするか、スタックから何かを取得します。割り当ては、スタックから最後のものを取得して割り当てます (この場合は、begin/end の最後の行)。多くの場合、これ (Ruby のスタック アプローチ) を知っておくと役立ちます。
私はそれが少なくとも驚くべきことではないと思いますが、それを使用するかどうかはユーザーの好みだと思います.
Ruby MRI 1.9 で生成されるバイトコード命令を見ると、予期しないことは何もしないことがわかります。
RubyVM::InstructionSequence::compile("c = begin; a = 5; 6; end").to_a
[:trace, 1],
[:trace, 1],
[:putobject, 5],
[:setlocal, 2],
[:trace, 1],
[:putobject, 6],
[:dup],
[:setlocal, 3],
[:leave]
Trace はスタック トレース専用です。無視してかまいません。Dup は、スタックの最後のアイテムを複製します。この例では、ローカル変数の番号は で、ローカル変数a
の2
番号はc
です3
(したがってputobject, 2
、 variable などに割り当てられますa
)。これと比較した場合の唯一の副作用a = 5; c = 6
はdup
命令です。つまり、メソッドのスタック サイズが 1 スロット大きくなります。ただし、これは特に重要ではありません。インタープリターがこの特定のメソッド内にある場合にのみ効果があり、スタックのメモリがとにかく事前に予約されているため、スタックポインターがそうでない場合よりも 1 だけ減分されることを意味するだけです。なので、基本的には変わりません。最適化をオンにすると、dup
おそらく消えます。