まだたとえ話で消耗してるの?

常に話題には乗り遅れる私ですが、ちょっと前、「変数を箱にたとえる」ことについて議論がありました。
プログラミングの変数を教えるときの「箱の説明」の是非について。 - Togetter
実のところこの話題は昔から何度も出てきた話で、「何周目だ」という話ではあります。私自身、「センス・オブ・プログラミング!」に書いたことがあります。
変数は「箱」か? - the code to rock

そして、上記の「the code to rock」の文章にもありますが、「箱モデル」の代わりとしてよく提唱されるのが「名札モデル」です。

こういうことは文章で書いてもわかりにくいので、それぞれ、絵にしてみましょうか。

箱モデル

■「a = 5;」という代入

「aという名前が付いた箱に、5という値を格納する」プログラミング言語の入門書によく出てくる説明ですね。

■それに続いて、「b = a;」という代入
ここで、以下のような、「aの箱から値を取り出してbの箱に入れる」というイメージをしてしまうと、

「この代入のあと、aの箱は空っぽになってしまうのでは?」という疑問が出るかもしれません。これが箱モデルの(欠点といえば)欠点です。
しかし、それ以前の話として、「5が代入されたaという変数は、5という値が書けるところなら基本どこにでも書け*1、5と同じ意味を持つ」、という原則からすれば、「b = a;」という代入は、結局「b = 5;」と変わりません。

こう考えれば、そう難しい話でもないのではないでしょうか。

名札モデル

さて、名札モデルです。名札というと、小学生が胸につけてるアレのイメージでしょうか。だとすると絵にするとこうでしょうか。

しかし、名札モデルの人のイメージでは、どうも名札モデルが重要なのは参照型の場合であるようなので、

ここではこんな、「紐付きラベル」で描いてみます。

■「a = 5;」という代入

「5というオブジェクトに、aという名札を付ける」と言えばよいでしょうか。

■それに続いて、「b = a;」という代入

「aという名札の先にあるオブジェクトに、bの名札を付ける」でしょうか。
しかし、先ほどの「5が代入されたaという変数は、5という値が書けるところなら基本どこにでも書け、5と同じ意味を持つ」という原則からすれば、「b = a;」は「b = 5;」と等しいので、以下のようにならないでしょうか。

いやそんなの前者に決まってるだろう何因縁つけてんだ、と思う人は、それに続いて、「c = 5;」という代入を行った際には、こちらをイメージするのでしょうか。

それともこちらでしょうか。

箱モデルなら悩む余地はありません。こうです。

初心者が最初に扱うのは基本型だ

実のところこんなことは、クラスみたいな参照型を使うときには疑問の余地なく決まることです。Pointクラスがあったとして、「p1 = p2;」なら、p1とp2は同じオブジェクトを指しますし、「p1 = new Point(10, 20); p2 = new Point(10, 20);」なら、(たとえ座標が同じでも)違うオブジェクトを指します。

しかし、プログラミング言語の入門で、最初に例に出すのは、intみたいな基本型でしょ? 違いますか?

まず、少なくともJavaなら、intはプリミティブであり、参照型ではないので、箱モデルの方が直接的でしょう。

Rubyなら……「Rubyはあらゆるものがオブジェクトだ!」という声が聞こえてきそうですが、Fixnumの実装云々を持ち出すまでもなく、FixnumもBignumもimmutableなので、実質、値型と同様に使えます。

  1. 初心者に、参照をイメージするような「名札モデル」を教え、
  2. その上で、整数型はimmutableだからこうなる、

と教えるよりは、最初は「箱モデル」で教えるほうがなんぼか無難ではないでしょうか(別に断言はしませんが)。

箱モデルで教えていて、次に参照を教えるときはどうするかって? 「参照値が入る箱」でよいのでは。

何が言いたいのかというと

この手の「変数は箱か名札か」的な話は、変数の挙動について「既にわかっている人達」が、「どっちが自然か」ということでケンケンゴウゴウするもので、実際にその議論が初心者のためになっているかというと、全然なっていない気がするんですよ。
経験的に、ですが、たとえば私と一緒に会社の新人研修を受けた人達(のうち本当の初心者)の中で、「変数」がわからなくて数日レベルで悩んでいる人はいませんでした。たぶん最初の説明は「箱モデル」で受けたと思うのですが、それでそこが突破できるなら別にそれでいい。それに、実のところ初心者にとって「あらゆるものがオブジェクトだ!」みたいな「統一性」は、言語を学ぶ際にはそれほど大きな助けにならない。あまりにもばらばらなのは考えものですが、整数型なんてのは、最初は値として考えておいて、「あらゆるものがオブジェクト」言語なら、後から「ああこれもオブジェクトなんだ」と理解(感動?)しても特に問題にならないと思います。ていうか、たいていの人は、この順序で理解したんじゃないかなあ。

そして、学習を進めるうちには、「変数は、スタックとかstaticとか、あるいはオブジェクトのメンバとして保持され、オブジェクトそのものはヒープに確保される」「オブジェクトを指し示す値が参照である」「参照値は、(実装により間接参照になってたりするかもしれないが)まあ要するにアドレスのことだ」ぐらいには、物理的な実装に近いところまで理解できるでしょうし、その知識は無駄にはならないでしょう(メンタルモデルとして有用ですし、パフォーマンス等を考えるならなおのこと)。

「センス・オブ・プログラミング」に以下のように書いたのは、そういう意味です。

しかし――変数が「箱」であるのか「メモ用紙」であるのか、そんなくだらない話を真剣に議論してもしょうがないでしょう。たとえ話は所詮たとえ話です。「変数」が実際にどのようなものかを知りたければ、結局、「メモリ」の話を抜きにすることはできないと思います。

というわけで、プログラミングする上では、ある程度低レベルの概念を知る必要が常にある、という意味で、宣伝につなげますよ。
「変数」を知りたければ結局「メモリ」を知らなければいけないように、WebアプリケーションプログラマならHTTPを知らなければいけません。そこでこの本ですよ。

ApacheのようなWebサーバを、自分で作ることにより、Webアプリケーション開発を真に納得して行うことができるようになります。

もちろん、最初に「箱モデル」で変数を学ぶことが悪いことではないように、最初に、HTTPをわかりもせずフレームワークを使ってWebアプリを作ってみることは悪いことではありません。しかし、いずれにしても、どうせすぐ必要になる知識です。「Webサーバを作るなんてマニアックな!」と思わず、読んでみてくださいませ。

余談

なぜ日本人はオブジェクト指向をなかなか理解できないのか?:新刊ピックアップ|技術評論社
くうだらない、じいつにくうだらない。
てかさ、

オブジェクト指向では,「データ」を「オブジェクト」として扱いますので,「変数」もまた「オブジェクト」と同じものだと言えます(※2)。

これからオブジェクト指向言語を学ぶ方は,ここで紹介した「変数とはオブジェクトのこと」というイメージを胸に,学習に臨んでみてください。

「変数とはオブジェクトのこと」って、はっきり間違いだろうよ。

*1:「3a」と書いたからといって「35」(さんじゅうご)にはならないので、この原則にも説明は必要ですが……