kwatchさんから「よくわかりません」というツッコミをもらいました。
「プログラマーのためのプログラマー日記」の最終日*1にも同様のことを書いておられたのを読んではいたのですが、 「もう少し解説してほしい」と頼まれれば、書くしかないでしょうね。
まず、「数学の概念とあまり合致しない」という点ですが、それはたぶんあまり重要ではないと考えています。 私が数学苦手なせいかもしれませんが。
そもそも数学の概念を持ち出しちゃうと、 プログラミング言語の代入って許せないものじゃないですか。
x = x + 1
とかありえないわけですし。よって数学における変数や代入のイメージに厳密に沿うと、
という関数型言語みたいな代入と変数しか許容できないような気がします。
え? 「そういう意味じゃない、そこまでは言ってない」ですって?
そうでしょうとも。では、「数学における変数や代入のイメージ」とはどんなものでしょう。
変数とは「関数のパラメータ」か「一時変数」であり、 「値(計算の途中結果)」に後で参照できるために名前をつけたものでしょう。 また、代入とは「値」に名前をつける行為です。
つまり、これは名札モデルです。 kwatchさんの直観とは反対に、名札モデルは数学の概念に合致しているわけですね。
たぶん、kwatchさんは「数学における変数や代入」という言葉で違うものをイメージしていらっしゃるとは 思うのですが、そのイメージは普遍的なものではないかもしれません。
「同じ説明は箱でもなりたつだろう」という指摘があるかもしれません。 もっともです。
問題は箱は名札と違って名前と強く結びついていないと言う点です。 現実世界の箱はむしろ入れ物としての性質が強く、変数よりもオブジェクトに近い性質を持ちます。 実際にCやC++では箱はオブジェクトです。
これを変数の説明に使ってしまうと後でオブジェクトと変数の区別が難しくなるんじゃないかと 心配しているんです。余計な心配かもしれませんが。
追記:
なんかフォローもらってますね。残念なことにどれもよくわかりませんでした(脳力が足りない?)。
Lisp だと箱に相当するのはシンボルでしょうか?
伝統的なLispのグローバル変数はそうでしょうね。
しかし、たとえ伝統的Lispでもローカル変数だと環境リストに格納されちゃうんで、 実装も名札モデルですよね。
「値に名前をつけたものが変数」というのは変ではないでしょうか。 実行時のある時点の文脈においてはそのように見えるかもしれませんが、 私の感覚だと「仮の名前(変数名)をもつ、後に与えうる未来の値が変数」というか。。
えー、なんで変なのかな。プログラム上のどこの地点で考えるかによるのでしょうか。 「仮の名前をもつ、後に与えうる未来の値」ってことは宣言した地点で考えているように 思われるのですが、Rubyには宣言はないしなあ。
名札モデルだと、代入っていうのは、名札を付け替えるのに相当するのでしょうか? これって、変数aとbがリファレンスで同じものを指していて、 b=1としたときに、aも1になるような場合の説明が難しいのではと思います。
えーと、C++にはリファレンスがあるのでそういうことが起きますが、 「もっと良い言語」であるRubyではそういうことは起きませんよね。 今は、Rubyの変数の話ですから、C++のリファレンスについて考える必要はないと思います。
CやC++の変数は確かに「箱+名札モデル」で説明するのがよかろうとは思いますが。
*1 「プログラマーのためのプログラマー日記」、終わっちゃったんですね、残念。
Lisp だと箱に相当するのはシンボルでしょうか?(初心者にはシンボルと名前(名札)の区別は付きにくいかも)
「値に名前をつけたものが変数」というのは変ではないでしょうか。実行時のある時点の文脈においてはそのように見えるかもしれませんが、私の感覚だと「仮の名前(変数名)をもつ、後に与えうる未来の値が変数」というか。。
名札モデルだと、代入っていうのは、名札を付け替えるのに相当するのでしょうか?
これって、変数aとbがリファレンスで同じものを指していて、
b=1としたときに、aも1になるような場合の説明が難しいのではと思います。
個人的には、箱モデルと名札モデルをあわせたのが変数かなと思っています。
箱に名札がついているというイメージですね。
1つの箱に複数の名札がついてるのを想像すれば、リファレンスも理解できそうですし。
名札を付け替えるというのと、名札のついてる箱の中身を変更するということの区別が必要になりますが、、、。
名づけによって文脈にとどめられた値、というのはわかるのですが。。その名前は<値への名づけ以前>、つまりコードを書いただけの段階でも存在するような気がしますし、その名前をもった抽象概念としての変数も存在するような。。。という混乱した気持ちが。。
箱モデルを支持されている方々は、変数を「値」いう属性と「get」「set」という操作を持ったオブジェクトに類するものと考えていらっしゃる気がします。
ですから「オブジェクトと変数の区別が難しくなるんじゃないか」という危惧がピンとこないのではないでしょうか?
実は私もどういう問題があるのかがわかっていないのですが。
ご回答いただき、ありがとうございます。
また長文で失礼します。
考え方の違いが端的に出ているのは、たぶんここですね。
『 変数とは「関数のパラメータ」か「一時変数」であり、
「値(計算の途中結果)」に後で参照できるために名前を
つけたものでしょう。また、代入とは「値」に名前を
つける行為です。』
自分としては、πやeといった定数なら値に名前をつける
という感覚はわからなくもないのですが、
「関数のパラメータ」や「一時変数」というのは、あとから
値を利用できるように箱にとっておく、つまり箱モデル
そのものと思っており、名前をつけるという感覚がまったく
ありません。
これは、数学には値という概念はあってもオブジェクトと
いう概念がないからだと思います。
例えば z = x+y を考えたとき、「x+yで新しいオブジェクト
が作成されて、それにzという名前をつける」という説明は、
Rubyでは有効でしょうが数学では不適切ではないでしょうか。
やはり数学では「xとyという箱から値を取り出して、両者を
足した値をzという箱にいれる」という説明のほうがしっくり
きます。
ですから、数学において名札モデルを使うのは、そういう
説明もできるでしょうがちょっとこじつけでは?と思って
ました。
しかしみんながそう感じているわけじゃないんですね。
自分は、数学ではみんな箱モデルで考えているだろう、
だから名札モデルは違和感を感じるんじゃないかと
思っていましたが、数学でも名札モデルで違和感が
ないのであれば、Rubyの説明でも名札モデルでいいと
思います。
というか、もうこうなったら初心者相手に実験するしか
ないですね。
「プログラミング初心者100人に聞きました。
どの説明がわかりやすいですか?
(1)名札モデル (2)箱モデル (3)IDをいれた箱モデル」
もうひとつ。『プログラミングでの「変数」や「代入」は、
数学とは違う』という意見について。
用語の意味が、プログラミングと数学とで異なっても
構わないとは思います。しかし、似ている必要はあります。
両者で意味や概念が似ているからこそ同じ用語を使うのであって、
意味や概念が異なれば異なる用語を使うべきです。
個人的には、Rubyで let x 100 のような記法があれば
名札モデルの説明がしっくりくるのですが。
これなら、代入ではなくて命名、変数ではなくて名前
という用語で説明がしやすい。
いや、見ためが違うだけといわれればそれまでですが。
それから、日記を読んでいただきありがとうございました。
まさかまつもとさんに読んでもらってるとは。光栄です。
いつかは復活させたいとは思っています。
Ruby限定の話というのを見落としてました。すいません。
ところで、Rubyって、複数の変数が同一の実体を指すこと無いのですか。参照渡しなんかも含めて。
複数の変数が同一の実体を指すことができると、それはそれで便利ですが、
Rubyではそうできなくなっている理由は何なのでしょう?
assignmentにsubstitutionと同じ「代入」という用語を当ててしまったのは、そういう意味では誤訳でしょう。
どこから始まったのかな。
僕も,名札モデルは「正しい」けど,箱モデルの方が分かりやすい人間です。その原因は頭のどこかで実装を意識しているためと思っていたのですが,一連の話で「x = 1」が「数学の代入」を連想するからだと思い至りました。「代入」というコトバからして,「箱にモノを入れる」ことを意識します。「x = x + 1」も「代入」として特に違和感はないですね。「等号」だとありまくりですが。
「名札」で違和感があるのは,「ary = Array.new」は「ある配列オブジェクトにaryという名前をつけた」ということですが,この「名前のないモノに名前をつける」ということが,あんまり日常では起きないからではないかとも思います。子供に名前をつけるときぐらい?
日本の「言霊」的な考え方をすると,「名前をつける」というのは非常に重要な作業なので,もっと気楽に扱いたい→「箱に入れるモデル」に流れるのかもしれません。