Edited at

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

More than 1 year has passed since last update.


概要

さて、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倍以上の開きがあるものに関しては、勝負は決したとして人気のある方にみんなもう寄せてしまっていいのではないかな、という印象を受けました。

あくまで私感ですが。

今回、調べて見て他にも面白い事が見つかっていますが、まぁそれに関しては別の記事で扱うのが良いでしょう。

何かしら参考にしていただけたなら幸いです。