Pythonのlen関数キモくない
どうも、Pythonのlen関数大好きマンです。Pythonのlen関数に関するポエムを垂れ流していきたいと思います。
言わずと知れたPythonのlen関数ですが、例えば以下のような使い方をします。
Python 3.6.5 (default, Apr 1 2018, 05:46:30)
[GCC 7.3.0] on linux
Type "help", "copyright", "credits" or "license" fo
r more information.
>>> list = [1, 2, 3]
>>> len(list)
3
>>>
Pythonではlist.len()
のように書かずこのように書くのです。オブジェクト指向への対応を謳う様々な言語でlist.len()
やlist.length()
のような書き方を採用しているので、このシンタックスはオブジェクト指向っぽく無い、などとしばしば議論になります。
私の主張は、むしろこのシンタックスこそがオブジェクト指向的だというものです。鉞お待ちしています。
len()について何が考えられたか
Pythonのlen関数について説明されているメーリングリストのアーカイブには以下のような記述があります。
First of all, I chose len(x) over x.len() for HCI reasons (def __len__() came much later). There are two intertwined reasons actually, both HCI:
この場合のHCIは、おそらくHuman Computer Interactionのことでしょう(間違っていたらごめんなさい)。この部分で言いたいことはlen(x)はx.len()よりもHCI的に優れている。つまり人間にとって読みやすいのはlen(x)の方であるということだと思います。このメーリングリストでは、その理由が2つ述べられています。
(a) For some operations, prefix notation just reads better than
postfix -- prefix (and infix!) operations have a long tradition in mathematics which likes notations where the visuals help the mathematician thinking about a problem. Compare the easy with which we rewrite a formula like x*(a+b) into xa + xb to the clumsiness of doing the same thing using a raw OO notation.
Postfix(x.len())よりもPrefix(len(x))の方が読みやすい場合があり、また、PrefixやInfixが数学では用いられ、数学者が問題を考える上で助けになってきたことが述べられています。
例として、x*(a+b)をxa + xbに書き直すことが挙げられています。
私見を述べると、Postfixを支持する人もa + bをa.add(b)と書いたり、x*(a + b)をx.mul(a.add(b))と書いたりするわけでは無いですし、このあたりを統一する意味はよくわかりませんし、それをもってオブジェクト指向的ではないと考えるのは早計だと感じます。
二つ目の理由として以下が挙げられています。
(b) When I read code that says > > > len(x) I know that it is asking for the length of something. This tells me two things: the result is an integer, and the argument is some kind of container. To the contrary, when I read x.len(), I have to already know that x is some kind of container implementing an interface or inheriting from a class that has a standard len(). Witness the confusion we occasionally have when a class that is not implementing a mapping has a get() or keys() method, or something that isn't a file has a write() method.
注目したのは前半の部分で、Pythonでは、len(x)と書くと、返り値が整数で、引数はコンテナです。x.len()と書くと、xに実装されているlenがスタンダードなものなのかを知っていなければなりません。
私見ですが、len関数はPythonのコンテナ回りの実装に関するメタ構造として機能している言うことができると考えます。
アラン・ケイはオブジェクト指向を始めとするソフトウエアの設計に関する多くの功績で知られていますが、アラン・ケイのソフトウエア工学は矛盾語法(oxymoron)か?という記事があり、ここには以下のようなことが書かれています。
しかし実際そんな事はまだ分からないので、機能満載の大規模設計の正反対であり、「機能なし」か、もっと良い言い方をすると「ほとんどメタ」のシステムが必要になる。残念ながら、現在のほとんどのソフトウェアは機能満載言語で書かれるのでこういったものには対応出来ない。
私より余程理解のある方の翻訳なので、翻訳の妥当性の検討などは省略しますが、アラン・ケイは「もっとメタを」ということを考えていたことが分かります。また、どうやらアラン・ケイは機能満載言語というものを嫌っていたということがわかり、言語機能そのものについてはシンプルであるべきだと考えていたことがわかります。
オブジェクト指向わからん
ここまで書いておいて心苦しいのですが、何がオブジェクト指向的かを判断するほど私がオブジェクト指向を理解していないことが分かりました。アラン・ケイが語っていたことが全てなのか、それとも各言語の様々な実装や実装に際する考え方を含むのかすら分かりません。
なのでここからは私見ですが、オブジェクト指向が目指していたものは、「オブジェクトに対して「もっとメタを」定義することで、そのメタに対して実装しやすくする。」ということだと考えています。「機能は少なく、メタ構造はきちんと」という方針は非常にオブジェクト指向的だと感じますし、Pythonのlen関数、ひいてはPython全体からそのような姿勢を感じます。