LoginSignup
21
10

More than 5 years have passed since last update.

rubyでどっちのメソッドが人気か調べてみた

Last updated at Posted at 2017-05-25

概要

さて、rubyのマニュアルを読んでいると同じ挙動だけど名前の違うメソッドがたくさん存在します。

代表としてはmapに対するcollectinjectに対するreduceなどでしょうが、このあたりはRubyの元にしたCommon LispとSmalltalkに存在するメソッドの両方の名前を採用したという歴史的経緯から、今の様な状態になっています。
どちらを使うのかは宗教論争と言われていて、どちらも使った人を自分も見たことはあります。
ただ、どっちを使った方が良いのか、そろそろ決着を見てもいいと感じたので、実際にはどちらのメソッドが人気なのか調べて見ました。

ちなみに、今回の調査対象は以下の様な基準で選びました。

  1. bestgems.orgでランキングされている人気のgemで、ダウンロード数Top 500のコードをサンプルにする
  2. 各々のgemの中のlibディレクトリ以下を調査の対象とした。つまりはテストのコードは集計から排除した
  3. 動的な言語なのでどのクラスに属しているかの推論は諦めて、あくまでメソッド名の集計結果とした。

Webプログラミングのためのものが多いとは言え様々なツールが入り乱れているrubygemsのコードを集めれば、熟達したRubyistのコードでしょうし、自分なりには妥当な基準だと考えています。

集計のためのコードはgithub上に、公開しておきます。
幾つか構文解析に失敗したファイルなども出ますが、統計的に無視して良い程度だと思われます。

結果

さて、では結果を順番に見ていきましょう。

まずは一番よく目にして気になっているであろうEnumerableモジュールの中のメソッドです。

Slalltalk由来 使用回数 Common Lisp由来  使用回数
collect 870 map 6843
inject 982 reduce 222
keep_if 10 select! 20 select + select! 合計 1629
delete_if 299 reject! 193 reject + reject! 合計 893

結果としては、それぞれ傾向はあれど、どちらのメソッドも使われている状態でした。
由来とした言語には関係が見えませんね。

意外だったのはdelete_ifメソッドの方がreduce!メソッドより多かった事ですね。
delete_ifは、実は「!」が付いていないのに破壊的メソッドという初心者が陥りがちなバグを生成する、落とし穴を持っているメソッドなので、好んで使う人がいたことに驚きですし、視覚的に分かりやすく、綴りも短いreject!メソッドよりも多いのがなお驚きです。
ただ、「!」の無いrejectメソッドが671回使われているので、これを足し合わせるとrejectreject!合わせて、893回使われています。
中の実例を見ていませんが、そもそもrejectを使って破壊的なメソッドとして扱わない方向に書き改めているのかもしれませんね。
select!メソッドこそ仕様回数20回ですが、selectメソッドは1609回と圧倒しているのもその証左でしょう。

やっぱり基本的には短くて分かりやすい名前を選んでいるという傾向に見えますが
それ以上の理由は見えない感じですね。

injectreduceに関しては、injectの方がよく使われていますが、これに関しては書籍ではinjectを使う例が多いのが理由と推測できますね。

それでは、その他のメソッドに関して順番に見ていきましょう。
メソッド名に関しては短い名前の方を先に掲載して、長い名前の方を続いて並べました。
仕様回数の多いメソッドから順番に掲載していっています。

順位 短い名前のメソッド 使用回数 長い名前のメソッド  使用回数
1 each 11728 each_pair 378
2 is_a? 7404 kind_of? 919
2 size 4055 length 2799
4 send 3183 __send__ 440
5 marge! 2727 update 506
6 dup 2471 clone 369
7 path 1926 filename 228
8 key? 1723 has_key? 1173
9 select 1609 find_all 172
10 pos 1334 tell 13
11 fail 932 raise 14119
12 class_eval 703 module_eval 469
13 pwd 220 getwd 10
14 next 215 succ 21
15 abs 192 magnitude 1
16 flat_map 191 collect_concat 0
17 to_enum 160 enum_for 86
18 local 92 mktime 1
19 tty? 74 isatty 2
20 class_exec 26 module_exec 10
21 rmdir 15 unlink 136
22 conj 6 conjugate 0
23 imag 5 imaginary 0
24 gm 4 utc 279
25 eof 3 eof? 128
26 value? 8 has_value? 5
27 iterator? 0 block_given? 1505

先ほども言いましたが、一般的な傾向としては、短い名前のメソッドの方がよく使われているし、使用頻度の高いメソッドほどその傾向があるという感じでしょうか、ただ例外も多いです。

例えばraisefailiterator?block_given?は圧倒的な差で綴りの長い方が使われています。
iterator?はそもそも公式ドキュメントで使用が推奨されていないという理由がありますし、raise公式ドキュメントでそちらを紹介しているのでこれも分かります。
また、File#eofFile#eof?に関しては、ファイルの終端に達しているかどうかを調べるメソッドですが、値がBooleanを返すため末尾に?の付くFile#eof?が圧倒的に好まれています。
ハッシュに指定したキーが存在しているかを調べるHash#key?Hash#has_key?は、それぞれ1723回と1173回と、名前の長さの違いの割に2倍以下の使用回数の差に収まっています。
これだけの綴りの長さの差があってもやはり、key?だけでは「持っている」いうニュアンスが抜けてしまうのが気になるのでしょうね。
Module#class_evalModule#module_evalも1文字程度の文字の違いを気にするよりは、使われる文脈がclassとmoduleどちらの内側で使われているかで使い分ける方が良いという風に考えられているのでしょう。
使用回数に大した差が見られません。

上記の様に、名前の短いことは好まれる理由の一つですが、論理と名前の整合性で違和感が表に出るものは、名前の長さよりもそちらが優先される。
また、Rubyの公式ドキュメントのサンプルコードでどちらが使われているかは大きな判断材料になっている状態で、全体像は若干複雑な様子です。

結論

さて、Rubyで人気のメソッドを参考に比較を行って見ましたが、個人的な結論としては調べて見た感じとして、使用回数に5倍以上の開きがあるものに関しては、勝負は決したとして人気のある方にみんなもう寄せてしまっていいのではないかな、という印象を受けました。
あくまで私感ですが。

今回、調べて見て他にも面白い事が見つかっていますが、まぁそれに関しては別の記事で扱うのが良いでしょう。
何かしら参考にしていただけたなら幸いです。

21
10
3

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
21
10