2012-03-30 4 views
2

Lispは、あなたが、その後元のために、いつでも戻って、値に設定することができますLispはシンボルをどのように動的に割り当てるのですか? Lispシンボルの基礎となるデータ構造/メカニズム

(setf mylist '(+ 1 2 A)) 

のようなリストに、このようなAやBなどの記号を定義することができます。 (set 'A 100)。この時点で(eval mylist)を実行し、103に戻ることができます。次に、Aを新しい値に繰り返し割り当てることができます。

Lispはリテラル "A"(シンボルの名前)とそれに割り当てられた値の両方を保存しているようです。これにより、動的な変数の割り当て/再割り当てが可能になります。ルックアップリストのようなものです。これを可能にする基礎となるデータ構造またはメカニズムは何ですか?

編集:具体的には、これは内部的に(またはパッケージが直接関与しているように見えるため外部から)どのように行われましたか? Lisp-2に実装されている方法に焦点を絞った詳細な技術的な答えを探しています。

+0

あなたはそれが実装されており、常に一つの方法で実装されていると思いますか? – ControlAltDel

+1

Stackoverflow FAQから: 'あなたは直面している実際の問題に基づいて実用的で、答えることができる質問をしてください。あなたの質問はあいまいであり、答えがあなたに役立つことは明らかではありません。プログラミング言語の実装についての本を読む方がよいでしょう。 –

+0

@ Rainerありがとうございます、今はっきりしていることを願っています。 –

答えて

5

'(+ 1 2 A)は変数ではなく、オブジェクトに評価される形式(quote(+ 112A))です。リスト内のAはシンボルですが、変数ではありません。

変数はシンボルで示される格納場所です。

Re:Lispのような言語は、実行時にこの種の評価をどのようにしますか?

(共通)Lispには、動的変数とレキシカル変数の2種類があります。動的変数は、実行時にシンボルを取得し、その変数に動的変数バインディングがあるかどうかを判断し、そのバインディングを取得または割り当てることができるという意味で評価できます。

字句変数は、コンパイル時に「ベーク」されたものです。それらを名前で反映する移植可能な方法はありません。

両方の種類の変数は、異なる目的に役立ちます。

動的変数は、値セルと呼ばれるシンボルに関連付けられた場所に格納できます。 (この用語は実際にはANSI Common Lispに現れます)。シンボルは、セルを取得するためのキーの一種として使用されます(セルがあれば)。例えば、値のセルは、キーが記号であるハッシュテーブルに格納されているいくつかのコンスセルのフィールドである可能性があります(cdr)。様々な実施が可能である。

Lispは動的変数のローカル再バインドをサポートしています。すなわち、letや他のバインディングコンストラクトを使用して、既存のバインディングを隠すダイナミック変数のローカルバインディングを作成できます。コンストラクトが終了すると(いずれの方法でも:throwなどを介して非ローカル出口を含む)、隠しバインディングが復元されます。この動的スコープは何らかの形で実装する必要があります。動的変数ルックアップは、必ずしもシンボルから値のセルへポインタを追うだけではありません。

さらに複雑になるのは、マルチスレッドのLispsのユーザーは、スレッドごとに動的変数をバインドする必要があるということです。

ここに詳細があるかもしれません:Common Lispのシンボルでhttp://en.wikipedia.org/wiki/Scope_%28computer_science%29#Dynamic_scoping

+0

すばらしい答えKaz。シンボル対変数についてはあなたが正しいと思っています。それはシンボルであり変数ではないことを明確にするためにqstを編集しました。だから、それはコンスセルがハッシュテーブルに格納されていると言っていますか? –

+0

私はそれがハッシュテーブルに格納されているコンスではないと言っていますが、可能です。値バインディングは、シンボルオブジェクト内からコンスに似たものへの直接ポインタにすぎないかもしれません。そのポインタは、シンボルの値の束縛(値のセルとの関連)であると理解されます。 '(makunbound )'はそのポインタを 'nil'で上書きし、シンボルに値のセル/バインディングを持たないようにすることができます。 (ただし、動的再バインディングとスレッドローカル動的変数の可能性について常に考えなければなりません。これらの要件は何とか表現に反映されなければなりません。) – Kaz

2

は、それらに関連付けられている値を持つ名前付きプロパティを持つことができる、自分の右にあるオブジェクトです。シンボルが作成されます(現在のパッケージにをインターン)ので、同様に、読み込みに:

> 'a 
A 

あなたは(ここではCLISPを使用して)(describe 'a)または(inspect 'a)でそれらを調べることができます。このシンボルは(set 'a 1)で設定できます。それ以降は(defun a (x) (+ 1 x))に電話することもできます。シンボル'aを検査すると、同時に値と機能定義の両方が保持されていることが明らかになりました。これは、Common Lispが変数の値と関数に別々の名前空間を持つことを反映しています。シンボルは、そのプロパティリストにこの追加情報を格納します。

[19]> (symbol-value 'a) 
1 
[20]> (symbol-function 'a) 
#<FUNCTION A (X) (DECLARE (SYSTEM::IN-DEFUN A)) (BLOCK A (+ X 1))> 
[21]> (symbol-plist 'a) 
(SYSTEM::DEFINITION 
((DEFUN A (X) (+ X 1)) . 
    #(NIL NIL NIL NIL ((DECLARATION OPTIMIZE DECLARATION))))) 

[44]> (setf (get 'a 'prop1) 12) 
12 
[45]> (symbol-plist 'a) 
(PROP1 12 SYSTEM::DEFINITION 
((DEFUN A (X) (+ X 1)) . 
    #(NIL NIL NIL NIL ((DECLARATION OPTIMIZE DECLARATION))))) 

も参照してください

http://www.lispworks.com/documentation/HyperSpec/Body/f_get.htm#get http://www.lispworks.com/documentation/HyperSpec/Body/f_intern.htm#intern

+1

非常に面白いです。 Lispシンボルは、値とコンパイルされた関数の両方を同時に定義することができます。 –

+0

@annoying_squidはい、それはLisp-2と呼ばれています。例えばスキーム。 Lisp-1である場合、Schemeの変数名と関数名に共通の名前空間が1つあります。 –

+0

Lispシンボルは、値と関数の両方を同時に定義することができます。同時に、異なる時間軸上の異なる値、同時にダイナミック変数とレキシカル変数を定義することもできます。同じシンボルは同時に、クラス、クラススロット、名前付きブロック、 'tagbody'ラベル、再起動の名前と、文法のルールのようなユーザ定義の抽象的な名前の名前です。 – Kaz

関連する問題