毎週日曜日に参加しているパーフェクトRails輪読会。9月6日に、gsub
の話が出ていて、自分も頭が混乱したので、整理してみる。
第5回パRails輪読会ノート(2020-09-06) - HackMD
String#gsub (Ruby 2.7.0 リファレンスマニュアル)
gsub
は、文字列を置き換えるメソッド。
次の例では、b
を0
に置き換えている。
irb(main):001:0> 'abcabc'.gsub(/b/, '0') => "a0ca0c"
下のように、ブロックを渡せることを知らなかった。
irb(main):002:0> 'abcabc'.gsub(/b/) { |str| str.upcase } => "aBcaBc"
自分でも動かしてみたのだが、これをやってみて混乱した。
irb(main):003:0> 'abcabc'.gsub(/[bc]/) { |str| p str } "b" "c" "b" "c" => "abcabc" irb(main):004:0> 'abcabc'.gsub(/[bc]/) { |str| puts str } b c b c => "aa"
上の例(p
)では返り値が"abcabc"
で、下の例(puts
)では"aa"
になっている。
結論から言うと、puts
の返り値がnil
だからだ。
irb で見てみる。
irb(main):023:0> p nil nil => nil irb(main):024:0> puts nil => nil
'abcabc'.gsub(/[bc]/) { |str| puts str }
では、/[bc]/
にマッチするb
とc
が、puts str
でnil
に置き換えられるので、返り値が"aa"
になる。
一方、p
は引数をそのまま返すので、b が b、c が c に置き換えられて(つまり何も置き換えないのと同じ)、全体の返り値は"abcabc"
になる。
Kernel.#puts (Ruby 2.7.0 リファレンスマニュアル)
Kernel.#p (Ruby 2.7.0 リファレンスマニュアル)
余談
puts
がnil
を返すことは知ってはいたのだが、こういう動きになることを理解していなかった。
今回のことがあって、改めて オブジェクト指向スクリプト言語 Ruby リファレンスマニュアル (Ruby 2.7.0 リファレンスマニュアル) の puts
と p
の項目を読んだ。
それでまたまた混乱したのが、#=>
という記号が、標準出力結果を表す場合と、返り値を表す場合があるということ。
たとえば、p
のサンプルコード。#=>
は、標準出力結果を表している。
puts "" #=> (空行) p "" #=> "" puts 50,"50" #=> 50 #=> 50 p 50,"50" #=> 50 #=> "50"
一方、String#empty? のサンプルコード。#=>
は、返り値を表している。
"hello".empty? #=> false " ".empty? #=> false "".empty? #=> true
#=>
についての説明があった。
p a #=> 1 の #=> って何?
「#=>」は標準出力に出力されるということを表しています。「p a #=> 1 」は「p a」を実行すると標準出力に「1」が出力されるという意味です。
このマニュアルのヘルプ (Ruby 2.7.0 リファレンスマニュアル)
xxx #=> 実行結果
xxx # => 実行結果
慣用的に実行結果を示すために使われるコメントの書き方。
Rubyで使われる記号の意味(正規表現の複雑な記号は除く) (Ruby 2.7.0 リファレンスマニュアル)
ということなので、間違いではなさそう。流れで見極めましょうということなのかな。