diff --git a/content/20240428125606 ダイナミックスコープ レキシカルスコープ.md b/content/20240428125606 ダイナミックスコープ レキシカルスコープ.md index cd4b7ee..9e9807d 100644 --- a/content/20240428125606 ダイナミックスコープ レキシカルスコープ.md +++ b/content/20240428125606 ダイナミックスコープ レキシカルスコープ.md @@ -14,7 +14,7 @@ 2. 同じ変数名の宣言、定義、変更などが来たら、実行時、最後にそうなった値を使う。関数に入ろうが、出ようが関係ない。 -現代(2024)のプログラミング言語では、1.が当然のように使われているため、1. 以外の方法がある可能性について、あまり考えたりすることが無い。 +現代(2024)のプログラミング言語では、1.が当然のように使われているため、1. 以外の方法がある可能性について、あまり考えたりすることが無い。なんでこのような違いができたのか?は理屈としてはネットの各地で説明されていると思う。 たとえば、以下のCプログラムで、画面に何が表示されるかを考えてみる。 ```c @@ -45,7 +45,7 @@ int main(void) ここで、`f1()`で定義した`int a`を`f2()`でも、(この書きかただと)参照できてしまうのが、ダイナミックスコープ。 その場合、画面には`1`が表示される(実際に試すことはできないけど)。 -レキシカルスコープの言語では、変数名とその参照先は一意に決まる。実行された状況などに左右されない。 +レキシカルスコープの言語では、変数名とその参照先は一意に決まる。実行された状況などに左右されない。ここでいう一意というのは、「同じ名前の変数が色々定義されてた場合、そのうちのどれ?」というのが(つまり、環境フレームが)一意という意味であって、その中身は実行された状況に左右されない、というわけではない。 ダイナミックスコープの言語では、変数の値がどうなっているかは、実行された状況に左右される(だからダイナミックスコープという)。 @@ -79,12 +79,13 @@ int main(void) } ``` -## 経緯とか +## 経緯とかお気持ちとか そもそもはレキシカルスコープにしたかったが、初期のLISPではダイナミックスコープになってしまったらしい。じゃあその頃、他の言語はどうだったんだ、とか、別途気になる。 レキシカルスコープがいかに重要なのか?とか、どうやったらそれが実現できるのか?をレキシカルスコープなschemeを作った人が書いたSICPが詳細に説明しているのは、そういう理由からかもしれない(根拠なし)。cf. [評価の環境モデル(SICP)](https://sicp.iijlab.net/fulltext/x320.html) -ちなみにレキシカルスコープのインタプリタを実装しようとすると、関数呼び出しのとき、別の関数を呼ぶ場合、呼び出し元で定義したローカル変数のかたまり(フレーム)を一旦無効にしてから関数を呼び出す必要があり、関数から戻って来た時にフレームを再度有効にする必要がある。この用途のため、フレーム保存しておく必要があるが、再帰呼び出しなどの時、(末尾再帰でないなら)毎回そのフレームを保存しておく必要があり、メモリ消費量が多くなる。というような、「ダイナミックスコープになった経緯」みたいな話をネットでチョイチョイ見るが、フレームの保存をしていないという、現代の視点から見るとバグっぽい挙動に見えてしまう。 +ちなみにレキシカルスコープのインタプリタを実装しようとすると、関数呼び出しのとき、別の関数を呼ぶ場合、呼び出し元で定義したローカル変数のかたまり(フレーム)を一旦無効にしてから関数を呼び出す必要があり、関数から戻って来た時にフレームを再度有効にする必要がある。この用途のため、フレーム保存しておく必要があるが、再帰呼び出しなどの時、(末尾再帰でないなら)毎回そのフレームを保存しておく必要があり、メモリ消費量が多くなる。というような、「ダイナミックスコープになった経緯」みたいな話をネットでチョイチョイ見るが、単純にフレームの保存をしていないという、現代の視点から見るとバグっぽい挙動に見えてしまう。 + ### Refs. - [変数束縛はLispのもう一つの本質である.](http://blog.livedoor.jp/s-koide/archives/1872474.html?ref=head_btn_prev&id=3054770)