関数でも、変数に入れられるので、不思議はないですかね。C言語とかなら、関数のタイプを書きますが、例えばint foo(a, b)のようで、この場合の割り算だと、0になると思いますが、Pythonの不思議なとこは、0.5となっているところですかね。関数とか変数のタイプを書かなくて良いのは楽ですが、落とし穴はないですかね。Rubyも変数のタイプとかなったように思いますが。
もう1個、似たような例ですが、関数の引数に関数を指定する。確かに上の図で、Nottori(dmyhiki)はそうなってます。その1個上の例と違うのはNottori(func)が定義されていて、実際の引数はここで決まっていることですね。
P081 第一級オブジェクトとしての関数
Kotlinでは関数も、数値や文字列などの他の値のように扱うことが出来ます。具体的には、変数に代入したり、関数の引数として与えたり、関数の結果としてかえしたりです。このような性質を持つオブジェクトのことを「第一級オブジェクト」(first-class object)と呼びます。つまりKotlinでは、関数も第一級オブジェクトなのです。
この説明には、続きがあって、混乱するので以下は省略します。Pythonも同じですね。
実の事言うと、関数が変数なんかに代入出来るのと「全てがオブジェクトである」ってのは関係ありません。
多分前、どっかでクジラ飛行机さんが書いた本参照してる、って言ってたような気がするんですが・・・。
この人、日本語プログラミング言語「なでしこ」の作者でハッカーなのは事実です。ただ、「全てがオブジェクトである」から関数が変数に代入出来るんだ、って説明は・・・正直言って不正確ですね。
いやそれ以前に。
実の事言うと「オブジェクト」ってのが何を表すのか定義がハッキリしてない、ってのが事実なんです。
プログラミング系の用語、って理学と違って、「バズワード」で広まっていつの間にか・・・ってケースが多々あるんで、良く分からないんだけど「みんなが言うからそう」ってのがあるんです。実の事いうとこの「オブジェクト」って言い回しもこの辺の「バズワード」から派生したようなモンだからややこしい。
通常、オブジェクトってのは大きく言うと次の二つを指します。
1. オブジェクト指向言語で作られたインスタンスをオブジェクト、と認識する。
2. 素のメモリを用いた「表現」ではなく、何らかの型的なラッパーで包み込んだ「状態」をオブジェクトと呼ぶ。
この二つが大体「☓☓がオブジェクト」と表現する場合なんですよね。
Cの場合は直接ハードウェア上のメモリを弄って解釈する「素の何か」を対象とするんで、オブジェクトとならない。一方Javaは仮想マシン上に色々とエラー制御を組み合わせた「データ」を扱うんで、これらはオブジェクトである、とかですね。
ところが、3つ目にこういう表現をする場合がある。
・☓☓言語に於いては全てはオブジェクトです。
これ、前にも書いたと思うんですが、通常この言い方をする場合、「ユーザーには関係がない」んですよ。
これが主張してるのは、大抵のケースの場合、
「この言語で扱うデータ型は全て一つのルートを持つヒエラルキーとして構成されている」
って事を言ってるだけだったりするんです。
例えば、Pythonの場合、全ての型(クラス)の基底クラスはオブジェクト(object)、となっています。
逆に言うと、Pythonの型システムは抽象クラスであるobjectがルートになっていて、どんなPythonの組込み型だろうと、これを辿って機能を継承してるのだ、と。
isamさんが仮に、ユーザー定義型として新しくクラスを作ったりしても、明示的に「親」を指定しなくても暗黙で遠い祖先にはobjectがある、と言う。必ずそういう構造になるのを「全てはオブジェクト」と表現するんです。そしてここには(このプログラミング言語で扱えるデータが)「全てはオブジェクトである」と。カッコが省かれている。
つまりですね、関数をデータとして扱うか扱わないか、ってのは設計者の方針に拠るんで、「全てはオブジェクトである」に通常関数は含まないんです。
要するに「関数を変数に代入出来る/出来ない」と「全てはオブジェクトである」は全く関係がない。
多分クジラ飛行机さんもその辺勘違いしてると思いますね。
っつーのは他にまた、「オブジェクト」って表現を使った紛らわしい言い回しがあるから、なんですよ。
これです。
「関数はファーストクラスオブジェクトである」
関数がファーストクラスオブジェクト、ないしは第一級オブジェクトだった場合、変数に代入出来るし、あるいは関数の引数としてそのまま受け渡す事が出来る。
つまり、Pythonでは「全てがオブジェクト」だから関数が変数に代入出来るのではなく、Pythonでは「関数がファーストクラスオブジェクト」だから変数に代入したり出来るんです。
しかも上の言い回しの場合、オブジェクトが何を意味するか、ってのはその前の説明の「プログラミング言語設計者が扱える全てのデータ型を共通のルートクラスから派生させたヒエラルキーとして設計してる」場合の「オブジェクト」と全く関係がないんです。
逆に言うと、「全てがオブジェクトじゃなくても」関数をファーストクラスオブジェクトにするように言語設計をすることは可能だし、「全てがオブジェクトでも」関数を変数に代入出来ないようにする事が出来る。
もう一度繰り返すけど、「全てがオブジェクト」と「関数が変数に代入出来る」と言う事象は直接は全く関係がないのです。理由にならない。そしてファーストクラスオブジェクトのオブジェクトはオブジェクト指向のオブジェクトでもないし、データ構造のヒエラルキーも指してない。全く「何となくオブジェクトと言っちゃった」以上の意味は無いんです(そういう意味ではオブジェクト指向の「オブジェクト」でさえそうですが)。
第一級オブジェクト:
https://ja.wikipedia.org/wiki/%E7%AC%AC%E4%B8%80%E7%B4%9A%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88
だからクジラ飛行机さんは明らかに勘違いしてますし、また、プログラミング言語の用語がバズワードを受け入れながら生成されていく、って事を鑑みても、「勘違いしてもしょーがない」とは思っています。プロのハッカーでさえそういう「間違い」を起こす。
と言うわけで、「全てがオブジェクトである」と言うのと「(Pythonでは)関数がファーストクラスオブジェクトである」と言うのを一緒くたにして考えるのは止めた方が良いです。
繰り返しますが、この二つはまったく別の事柄を指しているのです。