hagetak's blog

どうも、はげたかです。

Ruby:標準出力(p, puts, print)の違いを考察する

はじめに

先日、paizaの最終問題をクリアした。というのも、フォロワーさんの協力があったからだ。今まで曖昧だったRubyの標準出力を改めて学ぶ。

以下の変数を用い、各コマンド(関数)の出力結果を調べ、特徴を述べる。

2.1.1 :001 > str = "STR"
 => "STR" 
2.1.1 :002 > int = 100
 => 100 
2.1.1 :003 > array = ["a", "b", "c", "d", "e"]
 => ["a", "b", "c", "d", "e"] 
2.1.1 :004 > array2 = [["a","b"], ["c", "d"], ["e", "f"]]
 => [["a", "b"], ["c", "d"], ["e", "f"]] 

2.1.1 :008 > hash = {:john=>{name:"john", age:21}, :michael => {name:"michael", age:20}}
 => {:john=>{:name=>"john", :age=>21}, :michael=>{:name=>"michael", :age=>20}} 

p

pメソッドは、引数のオブジェクトを分かりやすい文字列にして標準出力に出力します。

わかりやすい文字列とはなんだろう。上の変数をすべて出力させる。

2.1.1 :012 > p
 => nil 
2.1.1 :013 > p str
"STR"
 => "STR" 
2.1.1 :014 > p int
100
 => 100 
2.1.1 :015 > p array
["a", "b", "c", "d", "e"]
 => ["a", "b", "c", "d", "e"] 
2.1.1 :016 > p array2
[["a", "b"], ["c", "d"], ["e", "f"]]
 => [["a", "b"], ["c", "d"], ["e", "f"]] 
2.1.1 :017 > p hash
{:john=>{:name=>"john", :age=>21}, :michael=>{:name=>"michael", :age=>20}}
 => {:john=>{:name=>"john", :age=>21}, :michael=>{:name=>"michael", :age=>20}} 
特徴
  • 改行を含まない
  • 戻り値も返す

puts

putsメソッドは、引数のオブジェクトを文字列に変換し、改行を加えて標準出力に出力します。

2.1.1 :019 > puts str
STR
 => nil 
2.1.1 :020 > puts int
100
 => nil 
2.1.1 :021 > puts array
a
b
c
d
e
 => nil 
2.1.1 :023 > puts array2
a
b
c
d
e
f
 => nil 
2.1.1 :024 > puts hash
{:john=>{:name=>"john", :age=>21}, :michael=>{:name=>"michael", :age=>20}}
 => nil 
特徴
  • 戻り値がnil
  • 改行を含む
  • 配列は要素1つ出力して改行を含む
  • str が文字列で出力されない

print

printメソッドは、引数のオブジェクトを文字列にして標準出力に出力します。

2.1.1 :035 > print str
STR => nil 
2.1.1 :036 > print int
100 => nil 
2.1.1 :037 > print array
["a", "b", "c", "d", "e"] => nil 
2.1.1 :038 > print array2
[["a", "b"], ["c", "d"], ["e", "f"]] => nil 
2.1.1 :039 > print hash
{:john=>{:name=>"john", :age=>21}, :michael=>{:name=>"michael", :age=>20}} => nil 
特徴
  • 戻り値はnil

爆弾問題の出力結果について

paizaの爆弾問題は、以下の出力結果が必要になる。

1 2 3
4 5 6
7 8 9

この出力結果になるよう、それぞれの関数で挑戦してみる。

2.1.1 :064 > array.each do |a|
2.1.1 :065 >     p a
2.1.1 :066?>   end
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
 => [[1, 2, 3], [4, 5, 6], [7, 8, 9]] 
2.1.1 :067 > array.each do |a|
2.1.1 :068 >     puts a
2.1.1 :069?>   end
1
2
3
4
5
6
7
8
9
 => [[1, 2, 3], [4, 5, 6], [7, 8, 9]] 
2.1.1 :070 > array.each do |a|
2.1.1 :071 >     print a
2.1.1 :072?>   end
[1, 2, 3][4, 5, 6][7, 8, 9] => [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

joinが必要とフォロワーさんから教わり...

2.1.1 :052 > array.each do |a|
2.1.1 :053 >     p a.join(' ')
2.1.1 :054?>   end
"1 2 3"
"4 5 6"
"7 8 9"
 => [[1, 2, 3], [4, 5, 6], [7, 8, 9]] 
2.1.1 :055 > array.each do |a|
2.1.1 :056 >     puts a.join(' ')
2.1.1 :057?>   end
1 2 3
4 5 6
7 8 9
 => [[1, 2, 3], [4, 5, 6], [7, 8, 9]] 
2.1.1 :058 > array.each do |a|
2.1.1 :059 >     print a.join(' ')
2.1.1 :060?>   end
1 2 34 5 67 8 9 => [[1, 2, 3], [4, 5, 6], [7, 8, 9]] 

配列 [1, 2, 3]、[4, 5, 6]または、[7, 8, 9]をjoinする(くっつける)と、こういう出力になるのか。今回も学ぶことがすごく多かったな〜

まとめ

今回わかった特徴を簡単に表にまとめてみる。

コマンド 戻り値 出力結果 改行
p わかりやすい文字列
puts nil 文字列
print nil 文字列

※ 汚いテーブルでごめんね。出力結果はせめてコマンドの隣か一番右だよね。

オープンソースを読むことも必要だと思い、rubyソースコードを読んでみた。

今更知ったけど、Cで書かれているのね。元は。わからないけど Ruby -> C -> 出力 みたいな手順なのかな。Rubyオープンソースを読むのはCを結構理解していないとダメなので。ぱっとみ、関数ポインタとかあって分からなかった。Cの知識を増やそう。

同時に、RailsならRubyソースコードでしょう。中身は。まずはRailsオープンソースを読む。

Kernel - Rubyリファレンス

プログラミング言語 Ruby

プログラミング言語 Ruby