LoginSignup
16

More than 5 years have passed since last update.

忘れられた出力メソッドObject#display

Last updated at Posted at 2015-12-19

はじめに

Rubyist はメソッドチェーンが大好きです。
ですが、表示など出力に関しては関数的メソッドである Kernel.#putsKernel.#printKernel.#p、そして Kernel.#sprintf(そのエイリアスとしての Kernel.#formatString#%(いわゆる%記法))を使うことがほとんどだと思われます。とはいえ、それで特に違和感は感じないでしょう。
他のプログラム言語から 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 はもちろん、IOStringIO などのインスタンスを渡せばいいわけです。(使ったことが無いクラスですが)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 と同じ処理を行うメソッドです。 文字列の出力を行うとき、ブロック付メソッド呼び出しと混在させられるので便利です。 printselectmap でのブロック呼び出しを混在させるときは表示前に一時変数に 退避させる必要がありますが、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 はメソッドチェーンが大好きです(大事なことなので強調しました)。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16