また、組み合わせることに注意してください
- 語彙スコープの概念(動的スコープとは対照的に、プログラミング言語にとっては良いことだと私たちは感じています)
- コードに深く埋め込まれた関数定義(ラムダ式)を使用する(このような定義を「ネストされた関数」と呼ぶこともできます)
言語実装の観点からも、プログラマーの観点からも、複雑な作業になる可能性があります。この複雑なものには特別な名前もあります:closure。
ウィキペディアが書いているように:
ファーストクラスのネストされた関数
を使用する言語での静的スコープの正しい実装は、各関数値が依存する変数の値のレコードを保持する必要があるため、簡単ではありません(関数とこの環境のペアは呼び出されます)クロージャ)。
これは、グローバル変数や可変変数(CやJavaなど)を使用して言語で実装するのは簡単ではないだけでなく、その場所でスコープ内にあった可変状態へのクロージャの評価時に正しいアクセスを確保することを検討してくださいネストされた関数定義の1つだけです。将来、クロージャを評価するときに、使用されたオブジェクトが破棄されてガベージコレクションされるべきではありませんでした)が、プログラマーがどのように閉鎖は複雑な状況で機能しますそして、それが正確に持つ(副次的な)効果(同じ理由で:クロージャを定義したときにスコープ内にあったすべての可変状態とクロージャの相互作用について考える必要があります。例:クロージャ内を参照する場合スコープ内にある外部の可変変数への定義。クロージャの定義時に変数が持っていた値に本当にアクセスしたいですか。つまり、変数の読み取り専用コピーが必要ですか。クロージャの評価時に、将来的に変数の可変状態に本格的にアクセスしたいですか?)。
純粋関数型言語では、入れ子関数の定義とその使用法について考える方がはるかに簡単であるため、字句スコープのみを持つことはまったく問題になりません。しかし、あなたの言語が機能していなければ、それはそれほど些細なことではありません。(これが、Javaにクロージャーを追加する方法が長い間議論されてきた理由の1つだと思います。クロージャーは、字句スコープの優れた概念に基づいているだけですが、プログラマーが理解するのに十分なほど些細なことではないようです。 。)
純粋関数型でない言語でネストされた関数について考えることは、動的スコープを使用すると簡単になります(ただし、動的スコープは適切ではありません。コンパイル時のチェックが少なくなり、動的スコープを使用したプログラムの正しい動作が保証されます)。
したがって、言語で動的スコープを使用できることの利点は、動的スコープのすべての危険性を考慮して、これを実行したい場合に、簡単な方法でいくつかのことをプログラムできる可能性もあると思います。
ノート
Javaでの(ない)クロージャの長い歴史について(そしてプログラマーがその概念を気に入らなかったこと)-http://people.csail.mit.edu/gregs/ll1-discuss-archive-html/msg04030.html:
日付:2003年8月14日木曜日08:05:44 -0700
差出人:Michael Vanier
件名:Re:バインディングと割り当て(以前は:Re:継続)
日付:2003年8月14日木曜日10:45:34 -0400
差出人:「DavidB.Tucker」
統計的な証拠はありませんが、匿名の内部クラス(クロージャ)内でローカル変数を参照するためにローカル変数を最終として宣言する要件はほとんど完全に不明であり、実際には使用されていないと思います。
好奇心から、Javaが匿名クラス内からの最終変数の参照のみを許可する理由を誰かが知っていますか?
デイブ
<cynic>Otherwise you'd have the equivalent of true closures,
and if you had that java would be a
*really* powerful and useful language, so they obviously couldn't do that.
</cynic>
実際、プロトタイプの実装で
は、内部クラス内から非最終変数を参照できました。これを望まないというユーザーからの抗議がありました!その理由は興味深いものでした。そのような変数をサポートするには、それらをヒープに割り当てる必要がありました。(少なくとも当時は)平均的なJavaプログラマーは、ヒープの割り当てやガベージコレクションなどについてまだかなり頭がおかしかったのです。彼らは、「new」キーワードの出現が見当たらないときに、「テーブルの下」でヒープ割り当てを実行する言語を承認しませんでした。
したがって、初期の頃は(明らかに)、Javaでは「3番目の」アプローチ(上記のテキストで言及した2つとは対照的)が採用されていました。「読み取り専用コピー」でも、実際のアクセスでもありません。評価から囲み(クロージャの定義時)の可変状態までの時間ですが、状態の可変コピー(少なくとも、引用された箇所をこのように理解しています;またはいいえ、彼はヒープ割り当てについて話しているのですか?参照だけですか?..それから2番目のオプションです。良いです。3番目のオプションは本当に私には意味がないように見えます。)彼らが最近Javaでクロージャをどのように実装しているかはわかりませんが、私はJavaに関する最近の新しい情報をフォローしていません。