感謝のプログラミング 10000時間

たどり着いた結果(さき)は、感謝でした。

Rubyのnilガードとは

スポンサーリンク

ユーザーからの入力などで、名前や電話番号などが入っていた場合があるとする。
これらをたとえばDBに入れようとしても、nilだとエラーになってしまうかもしれない。

そんなときに、nilを防ぐための書き方がある。
これをnilガードという。

実際に例を見てみよう。

class Person

  attr_accessor :last, :first

  def fullname
  	@last ||= ""
  	puts "#{@last.upcase},#{@first}"
  end
 end


takashi = Person.new

takashi.first = "takashi"
takashi.last = "sato"

#=>「SATO,takashi」と表示される
takashi.fullname 

takeshi = Person.new
takeshi.first = "世紀末リーダたけし"

#=>「,世紀末リーダたけし」と表示される
takeshi.fullname

この例では、

@last ||= ""

の部分で、nilガードを行っている。

@lastはnilなんだけど、upcaseを実行しても参照エラーにならない。
それは、ちゃんと@lastに""という空の文字列が入れられていたからだ。


この構文はちょっとわかりづらいけれど、

@last || (a = "")

と同じ意味だ。

その証拠に、fullnameメソッドを

def fullname
  @last || @last = ""
  puts "#{@last.upcase},#{@first}"
end

と変えても全く同じ結果になる。

「||」演算子は、被演算子のいずれかがtrueであれば、trueを返す。
そして、nilとfalse以外は全てtrueになるのが||演算子の特徴でもある。

つまり、最初の@lastの部分で、@lastがnilであるかどうか判定している。
そいで、nilであった場合は、1番目の判定(左側の判定)でfalseになって、
2番目の判定(右側)を行う。

そこで、@lastに""(空文字)を代入するという処理を行っている。

if文にするとこうなる。

  def fullname
  	if @last != nil
      @last = @last
    else
      @last = ""
    end

  	puts "#{@last.upcase},#{@first}"
  end

上のif文は、nilブロック構文と同じ意味だ。

最後に、2番目の演算をfalseにすると・・・

def fullname
  @last ||= false

  puts "#{@last.upcase},#{@first}"
end

upcaseでエラーが発生する。

tmp2.rb:8:in `fullname': undefined method `upcase' for false:FalseClass (NoMeth
dError)
        from tmp2.rb:24:in `<main>'


メタプログラミングRuby

メタプログラミングRuby

メタプログラミング Rubyの付録、p.268に書いてあった。
こういうtipsは「知ってるか知らないか」で違いが出る部分なので、しっかり押さえておきたいと思った。
本を読むまで知らなかったもん。