2016-10-25 5 views
0

「設定」機能私は難易度より多くの経験を持った人が理解することがコードのビットの仕組みを理解することだ

(let ((x 0)) 
    (loop for var in '(x) 
    do (set var 3)) 
    x) 

私の期待は式は、新しい値を3返すべきであるということですxは、実際には0を返します。なぜxはリセットされませんか?変数のリストを繰り返し処理して値を割り当てるもう1つの方法はありますか?

+2

「X」はレキシカル変数です。 'SET'はシンボルの値スロットだけを設定します(つまり、グローバル変数の値を設定します)。 – jkiiski

+1

@jkiiski:それは答えであり、コメントではありません。 – Svante

+1

['set'](http://clhs.lisp.se/Body/f_set.htm)は廃止予定ですので、使用しないでください。特殊なグローバルまたはレキシカルのバインディングを変更するには、 'setf'特殊形式を使用します。同じように見えるシンボルに基づいてバインディングを更新することは、おそらくハッシュテーブルのような他のデータ構造で解決する必要があります。 – Sylwester

答えて

7

シンボルを使用するレキシカル変数へのアクセスはサポートされていません。

Common Lispではシンボルを使って字句変数にアクセスすることはできません。デフォルトでは、変数はレキシカルにバインドされています。

特殊変数は動的バインディングを使用します。

これは、動的結合を使用する特殊な変数、で動作します:

CL-USER 14 > (let ((x 0)) 
       (declare (special x)) 
       (loop for var in '(x) do (set var 3)) 
       x) 
3 

別の方法としては、グローバル特殊変数を宣言することができ、特別な宣言はletバインディングにまで及びます。それが、命名規則で視覚的にマークする理由です。 fooではなく、*foo*と書いています。

CL-USER 15 > (defvar *x123* 0) 
*X123* 

CL-USER 16 > (let ((*x123* 1)) 
       (loop for var in '(*x123*) do (set var 3)) 
       *x123*) 
3 
+0

記号を使ってレキシカルヴァースにアクセスできないことを少しでも拡大できますか?例えば、字句変数には、print-name、symbol-value、symbol-function、propリストなどの通常のシンボルスロットがありますか?あるいは、lex varはシンボル値としてシンボルを持つことはありませんか?どんな説明にも感謝して、これが初心者であればごめんなさい。 (続き) – davypough

+0

第二に、私はグローバルバースの使用を避けることを望んでいました。ユーザーはvar名(マクロで取得)を提供します。現在、私はこれらのvar名(上記の例ではxという名前の変数)を持つlet節を(ロード時に)構築し、その値を本体に適切に設定しています。 lex varsで "set"が利用できない場合は、 "setq"(または "setf")だけが残っていますか?しかし、私はこれらのすべてのvar名をリストにグループ化することはできず、それぞれの変数をループ変数で処理することはできないようです。 let内の値(すべての数値)を設定する他の方法はありますか? (続き) – davypough

+0

私が持っていた唯一の別のアイデアは、おそらく別のユーザーパッケージを作成する(またはおそらく:キーワードパッケージを使用する)こと、そしてこれらの名前をそこに置くことです。しかし、これはいくつかの重要なコードの書き換え/再考を必要とするかもしれません。経験豊富な洞察力を求めてありがとう。 – davypough