はじめに
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` と同じ処理を行うメソッドです。 文字列の出力を行うとき、ブロック付メソッド呼び出しと混在させられるので便利です。 `print` と `select` や `map` でのブロック呼び出しを混在させるときは表示前に一時変数に 退避させる必要がありますが、`Object#display` メソッドを使えばその手間が省けるので 私はよく利用します。
[Rubyist Magazine - 標準添付ライブラリ紹介 【第 7 回】 net/http](http://magazine.rubyist.net/?cmd=view&p=0013-BundledLibraries&key=Object%23display)
ということで、知識としては頭に入ったのですが…(個人的には)使っていませんでしたw
# mruby には入ってなかった
ちょっと話が変わります。
今日、[mruby - iOSでRubyが書けるPictRuby - 平成を求める - Qiita](http://qiita.com/ongaeshi/items/e6dd9fd2e6f11b173c58) の記事を読んでから、mrubyに興味を持ちました[^4]。そしてバージョン1.2.0をインストールしました。
[^4]: 何周遅れなのでしょうか…。
そのときにふと `Object#display` メソッドを思い出し、 mruby に入っているのか確認してみました。
入ってませんでした。
でも mruby ももちろんオープンクラスに対応しているので、
>```rb
class Object
def display
print self.to_s
nil
end
end
とメソッド定義したところ、当然のように使えるようになりました。
これで mruby でも困りませんねw
最後に
Rubyist はメソッドチェーンが大好きです(大事なことなので強調しました)。