Ruby

「Ruby クイズ 5問 (初級)」が難問である件

Ruby クイズ 5問 (初級) に挑戦してみたのですが、とても難しかったです。

私の回答は下の方に書いてみました。回答を見る前に、皆さんもチャレンジしてみてください。

:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:

問題と回答

Q. puts と p の違いは?

A. 引数に対しての処理が大きく異なります。

pの場合の方が簡単なので、初めに説明します。

  1. 各引数について次を繰り返す。
    1. 引数に対して、inspectメソッドを呼び出し、文字列を得る。
    2. 得られた文字列を標準出力に表示する。
    3. 改行を標準出力に表示する。

putsの場合は引数が文字列か配列かそのどれでもないかによって異なります。

  • 引数が0個の場合
    1. 改行を標準出力に表示する。
  • 引数が1個以上の場合
    1. 各引数について次を繰り返す。
      • 引数が文字列の場合
        1. 引数の文字列を標準出力に表示する。
        2. 改行を標準出力に表示する。
      • 引数が配列の場合
        • 配列の要素が0個の場合
          1. (何もしない)
        • 配列の要素が1個以上の場合
          1. 配列の各要素を引数として再帰的に処理を行う。
      • 引数が文字列でも配列でもない場合
        • 引数にto_aryメソッドが定義されている場合
          1. 引数に対して、to_aryメソッドを呼び出し、配列を得る。
          2. 得られた配列を引数として再帰的に処理する。
        • 引数にto_aryメソッドが定義されていない場合
          1. 引数に対して、to_sメソッドを呼び出し、文字列を得る。
          2. 得られた文字列を引数として再帰的に処理する。

to_sが文字列を返さないなどのイレギュラーな処理を含めるともっと複雑になります。

Q. exit と exit! の違いは?

A. exit!はRuby上での終了処理を一切行わずにCでの_exit(2)で終了する。

exitによって行われるRubyの終了処理は単純ではありません。SystemExit例外、擬似シグナル、ENDブロック、ファイナライザ、exit(3)によるストリームのフラッシュなど多くの処理があります。それら全てを無視して終了するのが、exit!です。

Q. メソッド名のビックリ ( ! ) は何を表す?

A. メソッド名の一部。慣習により注意すべきメソッドに付けられます。

Rubyのメソッド名の末尾に!を付けることができます。!を含めてメソッド名であり、分離できません。慣習により次のようなメソッドに!を付けるようになっています。

  • 非破壊的メソッドと破壊的メソッドの両方がある場合、破壊的メソッドに付ける。
  • 安全なメソッドと危険なメソッドの両方がある場合、危険なメソッドに付ける。
  • その他、注意すべきメソッドに付ける。

対応する!がないメソッドがない場合もあります。また、メソッド名から破壊性や危険性が明確である場合は!を付けない場合があります。!がついていないから破壊しない、安全である、とは限りません。

あくまで慣習であり、組み込み以外の各ライブラリがこの慣習に従っているとは限りません。

Q. メソッド名のクエスチョン ( ? ) は何を表す?

A. メソッド名の一部。慣習により真偽値を返すメソッドに付けられます。

Rubyでは真偽値というひとくくりの型(クラス)はありません。どのようなオブジェクトであっても、真または偽のいずれかであるとみなされます。trueは真であるオブジェクトの代表、falseは偽であるオブジェクトの代表という扱いです。

?を含むメソッドは、慣習によりこのtrueまたはfalseのいずれかを返すメソッドに付けるようになっています。しかし、メソッド名から真偽値を返すことが期待できる場合は?を付けていない場合があります。

これもあくまで慣習であり、組み込み以外の各ライブラリがこの慣習に従っているとは限りません。

Q. インスタンスメソッドとクラスメソッドの違いは?

A. クラスメソッドはクラスの特異メソッド(特異クラスのインスタンスメソッド)です。

Rubyのメソッドは例外なく何かのインスタンスメソッドです。特異クラスのインスタンスメソッドを特異メソッド、クラスの特異メソッドをクラスメソッドと呼びますが、突き詰めれば、やはりそれは何かのインスタンスメソッドに過ぎません。

あるクラスのインスタンスメソッドとクラスメソッドの違いはと言われた場合、インスタンスメソッドはそのクラスのインスタンスから呼び出すことができますが、クラスメソッドは、そのクラスの特異クラスのインスタンスメソッドですので、そのクラスの特異クラスのインスタンス(それはそのクラスそのものただ一つです)から呼び出すことができる、となります。


初級でこのレベルと言うことは、中級や上級はどれだけ難しいお題になるのでしょうか…。