あるインスタンス変数にオブジェクトがセットされているときに、その参照を外しつつ、そのオブジェクトを返すというメソッドが必要になったんだよ。次のような感じだよ。

@name = nil #at initialize
 def set_name(name)
   @name = name
 end
 def reset_name
 end
 set_name('Charlie') # => "Charlie"
 reset_name # => "Charlie"

ここでreset_nameしたときに、インスタンス変数にセットされてたオブジェクトを返したいんだ。なんかよくありそうだよね。

こんなときは普通reset_nameを次のように書くと思うんだ。

def reset_name
   name = @name
   @name = nil
   name
 end
 set_name('Charlie') # => "Charlie"
 reset_name # => "Charlie"

でもなんかスマートじゃないよね。

で、少し考えたんだけど、多重代入を使うともう少しマシになるんだ。

def reset_name
   name, @name = @name, nil
   name
 end
 set_name('Charlie') # => "Charlie"
 reset_name # => "Charlie"

でもやっぱり返り値を確保するためだけにローカル変数を用意しなきゃならないなんて、なんかイケてないよね..

そこでObject#tapの出番ですよ奥さん..

def reset_name
   @name.tap { @name = nil }
 end
 set_name('Charlie') # => "Charlie"
 reset_name # => "Charlie"
 @name # => nil

tapはそのブロックを評価するけれども、その結果を捨ててしまうという、謙虚な変わり者のメソッドだよ。

なかなかイケてると思うんだけど、どうかな?

周知のTipsだったらごめんね



blog comments powered by Disqus
ruby_pack8

100円〜で好評発売中!
M'ELBORNE BOOKS