15

動的スコープ言語の例は何ですか?そして、そのデザインを選んだ理由は何ですか?実装しやすいからですか?

4

5 に答える 5

9

動的スコープの言語は、実装がはるかに簡単です。現在のアクティベーションレコード/スタックフレームにない変数にアクセスするには、制御リンクをたどるだけです。その場合、静的/字句アクセスリンクは不要であり、スタックフレームが小さくなります。

実際のスタックフレームがどの変数が使用されるかを知る必要があるため、動的変数は実行時に「予測不可能」になる可能性があります。この情報は、コードの静的構造を見ただけでは利用できません。プログラムの実際のコールグラフを実装時に予測するのが簡単でない場合、非常に簡単に捕らえられる可能性があります。そのため、今日のほとんどの言語には静的スコープがあります(ただし、ほとんどの例外システムは、これが最も実用的であるため動的です)。

ただし、場合によっては、動的スコープの変数が非常に便利です。たとえば、出力をリダイレクトする場合、動的変数を使用して、ローカルコードとそれ以降に呼び出されるすべてのコードの標準出力を設定できます。

(let ((*standard-output* *some-other-stream*))
 (stuff))

このcommon-lispの例(Seibelから)では、標準出力は、letフォームの期間中(囲んでいるparens内)、別のストリームにバインドされます。実行がレットを離れると、以前の状態に戻ります。良い議論については、http://gigamonkeys.com/book/variables.html Peter Seibelsの無料で優れた本、PracticalCommonLispを参照してください。Seibels自身の言葉で:

動的バインディングにより、グローバル変数ははるかに管理しやすくなりますが、それでも離れた場所でのアクションが可能であることに注意することが重要です。グローバル変数のバインドには、距離の影響が2つあります。これにより、ダウンストリームコードの動作が変わる可能性があります。また、ダウンストリームコードが、スタックの上位に確立されたバインディングに新しい値を割り当てる可能性もあります。動的変数は、これらの特性の一方または両方を利用する必要がある場合にのみ使用してください。

于 2009-09-25T15:11:24.920 に答える
9

Mathematica は、コンストラクトによって動的にスコープされる別の言語ですBlock。これは、数式を扱うときに実際に非常に便利です。次のようなものを書くことができます

 In[1]:= expr = a*t^2 + b*t+ c;

 In[2]:= Block[{a = 1, b = -1, c = 2}, Table[expr, {t, 5}]]
 Out[2]= {2, 4, 8, 14, 22}

aのような変数tがレキシカルにスコープされている場合、これはまったく機能しません。これは Mathematica のルール書き換えシステムと特にうまく連携します.このシステムは,とりわけ,既存の定義がない変数を(記号式として)評価しないままにします.

Mathematica は構文を使ってレキシカル スコープを偽造することができますModuleが,これが実際に行っているのは,一意であるとされる新しいシンボルに関して式を書き直すことです(次の一意のシンボルが何であるかを予測すると衝突が発生する可能性がありますが,これはほとんどの場合簡単です).これの意味は

Module[{x = 4}, 
  Table[x * t, {t, 5}]]

次のようなものに変換されます。

Block[{x$134 = 4},
  Table[x$134 * t, {t, 5}]

lexical-letEmacs Lisp は、そのライブラリーの 1 つに、レキシカルスコープを偽造するためにまったく同じトリックを引っ張るという構造体 (実際には Lisp マクロ) を持っています。

ELisp や Mathematica の偽のレキシカルでは得られない、言語をコンパイルするときの実際のレキシカル スコープには、パフォーマンス上の利点があります。これは、動的変数とその現在の値の間のマッピングが必要になるためです。ハッシュ テーブルまたはプロパティ リストなど) と追加の間接レイヤー。

EDIT : レキシカル変数しかない場合は、スコープに入るときにグローバルなレキシカル変数の元の値を保存し、スコープを出るときに古い値が復元されることを保証することで、動的スコープを偽造できます。それを確実にするために、LispUNWIND-PROTECTfinallyブロックのようなものが必要になります。私はこれが C++ デストラクタを使用して行われるのを見てきましたが、ほとんどが演習としてです。

于 2009-09-24T19:39:50.433 に答える
3

ええと、賛否両論を議論するウェブサイトがたくさんあるので、私はそこに行きません。

動的スコープにかすかに似ているいくつかの機能を備えた興味深い言語の1つは、XSLTです。XSLTのテンプレートや変数などは字句スコープですが、XSLTはもちろんすべてXMLに関するものであり、コンテキストノードがグローバルであり、XPath式が評価されないという意味で、xmlツリーの現在の位置は「動的スコープ」です。 XSLTの字句スコープによるが、動的評価による。

于 2009-09-24T17:55:22.253 に答える
3

動的スコープは、インタープリターを使用して実装する方が簡単です。初期の Lisp インタープリターのほとんどは、動的スコープを使用していました。数年後、レキシカル スコープに利点があることが判明しましたが、最初は主に Lisp コンパイラで実装されました。解釈されたコードに動的スコープを実装し、コンパイルされたコードに字句スコープを実装するいくつかの実装が登場しました。クロージャーを提供するために特別な言語構造を提供するものもありました。そのとき、Scheme や Common Lisp のような Lisp の方言は、解釈されたコードとコンパイルされたコードとの間に違いがないことを必要とし、したがって解釈ベースの実装は字句スコープも実装しなければなりませんでした。

初期の Smalltalk 実装では、動的スコープが実装されていました。すべての種類の Lisp 方言の実装が動的スコープを実装しました (Interlisp、UCI Lisp、Lisp Machine Lisp、MacLisp、...)。

過去 20 年間のほとんどすべての新しい Lisp 方言は、デフォルトで、または排他的にレキシカル スコープを使用しています。いくつかの出版物で、字句スコープを使用して Lisp を実装する方法が詳細に説明されています。したがって、字句スコープを使用しない言い訳はありません。

于 2010-06-15T22:02:25.627 に答える