Ruby についてのクイズです。
ある正しいプログラムの一箇所をスペルミスして SyntaxError が発生することはあるでしょうか。
ここで「スペルミス」とは,英単語の綴りの中のアルファベットを別のアルファベットに間違えること,とします。
なお,eval
などの「文字列をスクリプトとして実行する」系のメソッドを使うと簡単に作れてしまうので,その手のメソッドは使わないという制約を設けます。
答えはスクロールで
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
⏬
こんなコードで SyntaxError が起きます。
def refined?(mod, hoge)
# 定義は省略
end
p defined?(String, :gsub)
refined?
は,あるモジュールのあるメソッドが refinements で置き換えられているかどうかを判定するメソッドのつもりです。そういうメソッドは原理的に可能ですが,中身は略します。
さて,最終行でそのメソッドを使おうとしたのですが,「R」のキーを押すつもりで斜め下の「D」を押してしまい,refined?
が defined?
になってしまいました。
メソッド名をスペルミスすると,NameError か NoMethodError のどちらかが出るはずですよね1。なぜ SyntaxError になるのでしょうか?
述語メソッドのような見た目の defined? は,実は演算子なのです。
そりゃ,こいつがもしメソッドだったら辻褄が合わないでしょ。
defnined?
は,与えられた式がローカル変数なのか定数なのか代入式なのか(等々),はたまた未定義のものなのか,といった「種別」を返すものです。
もしメソッドだったら,defined?
の呼び出しに際して,まずは与えられた式を「評価」しなくちゃなりません。評価しちゃうとオブジェクトになっちゃいますよね。それに,未定義だったら呼び出しが起こる前にエラーが出ちゃいます。
話を元に戻しましょう。
defined?(String, :gsub)
の defined?
は,refined?
をタイポしちゃったためにメソッドではなく演算子になっちゃいました。
defined?
に与える式は ( )
で囲っても構わないのですが,二つの式をカンマで区切って併記することを認めていません。だから構文エラー(SyntaxError)になる,というわけです。
-
復習しておくと,ローカル変数の参照とも解釈しうる名前なら NameError になり,そう解釈しえないメソッド呼び出しなら NoMethodError になる。 ↩