コードを読んで Ruby を学ぼうとしているのですが、どのチュートリアルやチートシートにも載っていない次のような状況に遭遇しました。
def foo!
# do bar
return bar
end
「!」のポイントは何ですか?メソッド定義で?
コードを読んで Ruby を学ぼうとしているのですが、どのチュートリアルやチートシートにも載っていない次のような状況に遭遇しました。
def foo!
# do bar
return bar
end
「!」のポイントは何ですか?メソッド定義で?
!
Ruby は、メソッド名の末尾にある を特殊文字として扱いません。慣例により、で終わるメソッドに!
は、メソッドの作成者が注意を引こうとしている何らかの副作用またはその他の問題があります。例としては、インプレース変更を行うメソッド、例外をスローするメソッド、または警告にもかかわらずアクションを続行するメソッドがあります。
たとえば、次のようString#upcase!
に を比較しString#upcase
ます。
1.9.3p392 :004 > foo = "whatever"
=> "whatever"
1.9.3p392 :005 > foo.upcase
=> "WHATEVER"
1.9.3p392 :006 > foo
=> "whatever"
1.9.3p392 :007 > foo.upcase!
=> "WHATEVER"
1.9.3p392 :008 > foo
=> "WHATEVER"
ActiveRecord はsave!
、失敗時に例外を発生させる (vssave
は true/false を返しますが、例外は発生させません) のようなものに対して bang-methods を広範囲に使用します。
それは「ヘッズアップ!」です。フラグですが、これを強制するものは何もありません。!
人々を混乱させたり怖がらせたりしたい場合は、すべてのメソッドを で終了できます。
!
は受信者を変更する "bang" メソッドであり、Ruby の慣例です。
bang 以外のメソッドのように機能するバージョンを定義することはできます!
が、その場合、他のプログラマーがメソッド定義を見ていない場合、誤解を招く可能性があります。
bang メソッドはnil
、レシーバーに変更が加えられていない場合に戻ります。
なしの例!
- ソース文字列が変更されていないことがわかります。
str = "hello"
p str.delete("l") #=> "heo"
p str #=> "hello"
使用例!
- ソース文字列が変更されていることがわかります。
str = "hello"
p str.delete!("l") #=> "heo"
p str #=> "heo"
注: bang 以外のバージョンのメソッドがいくつかあり、これらもレシーバー オブジェクトを変更できます。
str = "hello"
p str.concat(" world") #=> "hello world"
p str #=> "hello world"
!
はメソッド定義ではありませんが、メソッドを宣言するときに使用される規則であり、このメソッドはオブジェクトを変更します。
1.9.3-p194 :004 > a="hello "
=> "hello "
1.9.3-p194 :005 > a.strip
=> "hello"
1.9.3-p194 :006 > a
=> "hello "
1.9.3-p194 :007 > a.strip!
=> "hello"
1.9.3-p194 :008 > a
=> "hello"