Effective Ruby: Perlっぽい記号やめようぜ

項目3 Rubyの暗号めいたPerl風機能を避けよう

お題目は、その通り!!という感じです。
 
例が面白かったのでご紹介。

while readline
  print if ~ /^ERROR:/
end

ぱっと見、各行頭がERROR: で始まるものを出力しそうだというのは分かりますが、具体的にどうなっているかは分かりませんでした。
 
解説すると、
Kernel#readline(IO#readlineとは違う)が標準入力から行を読み出し値を返すが、その際に$_変数にもセットする。
同様に、Kernel#printは引数なしで呼び出された時に、$_変数の内容を標準出力に書き込む。
Regexp#~演算子は、右側の正規表現$_変数の内容をマッチさせようとする。マッチがあればその位置を返し、そうでなければnilを返す。
 
という具合にとても複雑だ。

覚えておくべき事項

  • String=~ ではなく、String#matchを使おう。String#matchなら、複数の特殊グローバル変数ではなく、MatchDataオブジェクトにすべてのマッチ情報を返す。
  • 短い暗号めいた名前のグローバル変数ではなく、長くて意味のわかる別名の方を使おう(例えば、$:ではなく、$LOAD_PATH)。ただし、ほとんどの長い名前は、Englishライブラリをロードしなければ使えない。
  • 暗黙のうちに$_グローバル変数を良い書きするメソッドを使うのを避けよう(たとえば、Kernel#printRegexp#~など)

English ライブラリについて

知ってはいましたが、使ったことないやつです。
ERROR_INFO、ERROR_POSITION、PID、MATCH、PREMATCH、POSTMATCH あたりは使う可能性はあるか。

$ grep alias ./versions/2.5.0/lib/ruby/2.5.0/English.rb
#  Below is a full list of descriptive aliases and their associated global
alias $ERROR_INFO              $!
alias $ERROR_POSITION          $@
alias $FS                      $;
alias $FIELD_SEPARATOR         $;
alias $OFS                     $,
alias $OUTPUT_FIELD_SEPARATOR  $,
alias $RS                      $/
alias $INPUT_RECORD_SEPARATOR  $/
alias $ORS                     $\
alias $OUTPUT_RECORD_SEPARATOR $\
alias $INPUT_LINE_NUMBER       $.
alias $NR                      $.
alias $LAST_READ_LINE          $_
alias $DEFAULT_OUTPUT          $>
alias $DEFAULT_INPUT           $<
alias $PID                     $$
alias $PROCESS_ID              $$
alias $CHILD_STATUS            $?
alias $LAST_MATCH_INFO         $~
alias $IGNORECASE              $=
alias $ARGV                    $*
alias $MATCH                   $&
alias $PREMATCH                $`
alias $POSTMATCH               $'
alias $LAST_PAREN_MATCH        $+

ご参考

$@ などの特殊変数をわかりやすい英語名で使用する - わからん

Effective Ruby

Effective Ruby