クロージャと記号論理学と高校数学
今日大学で、C#の本を持ってる人がいたことからC#の話になり、最近のC#はクロージャが使えるらしいよ*1、というところから長ば強引に「クロージャを知りたいならSchemeが一番」とSchemeの宣伝に持っていった。そこで説明するときにとっさに"自由変数"と"束縛変数"という言葉が出てきたんだけど、この2つの言葉が理解できていれば、クロージャの理解はわりと一瞬でできるんじゃないだろうか。
自由変数と束縛変数。この2つの概念を陽に初めて扱ったのは大学1年夏学期*2の記号論理学だった。記号論理学の中でも、自然演繹のsyntaxだったので、意味を一切考えずに記号をルール通りに扱うだけでいろんな結論が得られるよね、というやつだった。そのルールを守る上で、*3自由変数と束縛変数を明確に区別する必要があった。
自由変数と束縛変数というと難しく聞こえるかもしれないが、この2つは実にありふれた概念で、高校数学をちょっとやってれば確実に無意識のうちに扱っている。例えば、次の2つの関数を考えてみる。
この2つの違いがわかるだろうか?大体の高校では、関数のイメージを掴むためにはグラフを描け、と言われていると思うので、この2つの関数をグラフに描いてみて比較してみよう。
何?g(x)のほうはaの値がないから具体的なものをプロットできない?じゃあ、自由に値を選んで、適当にいくつかプロットしてみたら?
このa、つまり実際に使おうと思ったときに値がわからない奴が"自由変数"ってやつだ。高校では"定数"なんて呼ばれていて、若き日のはやみずはずっとこの呼び方にモヤモヤを感じていた。実際に使うときに、状況によって"変化"するのはaとかbとかなのに、なんでやつらは常に一定であるような"定数"なんて名前なんだ、と。二次方程式の解だって、変数xの値を決めているのはのa,b,cなのに。
高校時代に"変数"と呼んでいたものの99%は"束縛変数"、つまり使うときに値がわからないから困ることがないやつらだ(のプロットならxに定義域の値を次々に入れればいいし、なら解くだけだから結果的にはわかる)。
そして、"定数"とか呼んでいた"変数"(束縛変数)以外の文字は99%が自由変数、つまり使うときに値がわからなくて困るやつら。
しかし、高校で数学をやっていて、「この定数の値がわからないから困った」なんてことがあっただろうか。おそらくほとんどの人はないはず*4。なぜなら、ある数式、例えば二次方程式の解だけを見たときには、a,b,cはわからないけど、テストの問題を解くときにはa,b,cが与えられているから。
この、「a,b,cが与えられる」というのは、まさに「a,b,cを束縛する」ことであり、そのテスト問題の中では「a,b,cもまた束縛変数」となっている。つまり、数式単体では自由変数が存在していたとしても、数式を仕様する状況がその自由変数の値を決めることが、自由変数を束縛して束縛変数にすることになる。
自由変数に値を与えることが、自由変数を束縛変数に変えること。
書いていて疲れてきたので突然だけどここで終了。いろいろ書きたいことは溢れているけど、収拾がつかなくなりそうなので。明日実験だし。箇条書きでメモ。
- 自由変数が全てなくなった時点で、1つの具体的な答が出る*5
- プログラムで言いかえると、自由変数がすべて無くなった時点で、そのプログラムは実行可能(コンパイル可能)になる
- 自由変数が存在するからこそ、ほげほげの定理の数式は有用である
- 自由変数が全く存在しないと、一般性がない
- つまり、自由変数は力だ
- プログラムで自由変数をどう扱うかの違いが、Dynamic bindingとLexical bindingの違い。
- lambda式を評価した時点で、lambda式内の自由変数(大域的には束縛変数)がどの値を指しているか、というポインタのリストが環境(?)で、クロージャはその環境を保持しているのがただの関数と違うところ。
- (無名)関数とクロージャの違いは、lambda式内に自由変数があるか否か
とまあ、こんなことを今日の数学の授業中に考えていたおかげで、離散フーリエ変換の授業聞いてなかった。
ちなみに、クロージャについてはhttp://capsctrl.que.jp/kdmsnr/wiki/bliki/?Closureがわかりやすくていい感じ。自分はここでクロージャのなんとなくの意味がわかって、あとはSchemeを愛でるうちに体得した。
ツッコミ歓迎。