はじめに
Rubyist はメソッドチェーンが大好きです。
ですが、表示など出力に関しては関数的メソッドである Kernel.#puts
、 Kernel.#print
、 Kernel.#p
、そして Kernel.#sprintf
(そのエイリアスとしての Kernel.#format
や String#%
(いわゆる%
記法))を使うことがほとんどだと思われます。とはいえ、それで特に違和感は感じないでしょう。
他のプログラム言語から Ruby に入ってきたひとも、関数的メソッドであれば違和感無く使えるでしょうし、そのような方であればメソッドチェーンで出力したい、と思うことは(まず)ないでしょう。
さて。
私は以前、Kernel.#puts
を使ったときに、その引数にブロックが付いた場合、do … end
と { … }
とで結合強度が違うことから不思議な挙動に触れて、それをネタに投稿をしたことがあります(とうとう100ストックに到達しました、ありがとうございます)。
そのときに次のようなコメントを頂きました。
この場合、
(1..10).inject(0) do |sum, i|; sum + i; end.tap{|t| p t}
と、endの後に続ければいいんじゃね?
そう、出力もメソッドチェーンで行えばいいのです。
Rubyist はメソッドチェーンが大好きです(大事なことなので2度言いました)。
実は tap
しなくても、そのようなメソッドが存在するのです。ということで、本投稿ではそのメソッドを取り上げます。それがタイトルに掲げた Object#display
です。
Object#display
前置きが長くなりました。
るりまには以下のように記載されています。
instance method
Object#display
display(out = $stdout)
->nil
オブジェクトをout
に出力します。以下のように定義されています。
class Object def display(out = $stdout) out.print self.to_s nil end end
メソッドの定義まで書いてあるるりまはちょっと珍しいと思います。
返値は Kernel.#print
メソッドと同様に nil
が返ります。なのでこの先はメソッドチェーンできません。すこし残念ですね[^0]。
[^0]: 続けたければ Object#tap
しちゃいましょう。
引数には出力先となるオブジェクトを渡します(普段の出力先は $stdout
でしょうから引数無しでいいでしょう)。ということは、print
メソッドの存在するクラスのインスタンスを渡せばどのようなところへも出力できる、ということになります。 Rubyist の好きな Duck Typing です。つまり Kernel
はもちろん、IO
や StringIO
などのインスタンスを渡せばいいわけです。(使ったことが無いクラスですが)Net::Telnet
インスタンスなどにも使えそうです[^1]。便利ですね。
[^1]: そこまでいくと便利なのか謎ですが。
なお、このメソッドは遅くとも(私の手元にある一番古い環境である) Ruby 1.8.7 から存在しています。
使い方
ブロックの結合強度なんか気にしなくていいです。
出力したいインスタンスの末尾に付けてしまえばいいんです。
(1..10).inject(0) do |sum, i|; sum + i; end.display
と書いちゃえばいいんです[^2]。
[^2]: ただしdo … end
のあとに続くことによる違和感はどうしても残りますね。{ … }
のあとに書くと良いと思います。
メソッドチェーンで Kernel.#p
の代わりになるメソッドは?
Object#display
メソッドの直前に Object#inspect
メソッドを入れてしまえば OK です。
〜.inspect.display
って感じです。
Object#display
を知ったきっかけ
数ヶ月前になりますが、るびまを読んでいて知りました[^3]。
[^3]: 0013号の記事なので、2006年2月には既に存在していたメソッドですね。
Object#display
は$stdout.print obj
と同じ処理を行うメソッドです。 文字列の出力を行うとき、ブロック付メソッド呼び出しと混在させられるので便利です。select
やmap
でのブロック呼び出しを混在させるときは表示前に一時変数に 退避させる必要がありますが、Object#display
メソッドを使えばその手間が省けるので 私はよく利用します。
Rubyist Magazine - 標準添付ライブラリ紹介 【第 7 回】 net/http
ということで、知識としては頭に入ったのですが…(個人的には)使っていませんでしたw
mruby には入ってなかった
ちょっと話が変わります。
今日、mruby - iOSでRubyが書けるPictRuby - 平成を求める - Qiita の記事を読んでから、mrubyに興味を持ちました[^4]。そしてバージョン1.2.0をインストールしました。
[^4]: 何周遅れなのでしょうか…。
そのときにふと Object#display
メソッドを思い出し、 mruby に入っているのか確認してみました。
入ってませんでした。
でも mruby ももちろんオープンクラスに対応しているので、
class Object def display print self.to_s nil end end
とメソッド定義したところ、当然のように使えるようになりました。
これで mruby でも困りませんねw
最後に
Rubyist はメソッドチェーンが大好きです(大事なことなので強調しました)。