49

同様の質問を見つけました。

しかし、その説明がよくわかりません。

だから私は次の例でclispを実行しようとしています:

  [1]> (defvar a 5)
  A
  [2]> (+ a 1)
  6
  [3]> (defparameter b 5)
  B
  [4]> (+ b 1)
  6
  [5]> (setf c 5)
  5
  [6]> (+ c 1)
  6
  [7]> (setq d 5)
  5
  [8]> (+ d 1)
  6
  [9]> (let ((a 500)) (+ a 1))
  501
  [10]> (let ((b 500)) (+ b 1))
  501
  [11]> (let ((c 500)) (+ c 1))
  501
  [12]> (let ((d 500)) (+ d 1))
  501
  [13]> 

私が見つけたものはまったく同じです。

何が違うのかわからない?

4

2 に答える 2

74

DEFPARAMETER always assigns a value. So:

[1]> (defparameter a 1)
A
[2]> (defparameter a 2)
A
[3]> a
2

while DEFVAR does it only once, so:

[4]> (defvar b 1)
B
[5]> (defvar b 2)
B
[6]> b
1

SETF is a macro which uses SETQ internally, but has more possibilities. In a way it's a more general assignment operator. E.g. with SETF you can do:

[19]> (defparameter c (list 1 2 3))
[21]> (setf (car c) 42)                                              
42
[22]> c
(42 2 3)

but you can't do that with SETQ:

[23]> (setq (car c) 42)                                              
*** - SETQ: (CAR C) is not a symbol
The following restarts are available:
USE-VALUE      :R1      Input a value to be used instead.
ABORT          :R2      Abort main loop
Break 1 [24]> abort
于 2012-01-19T14:47:58.360 に答える
27

と の両方defvardefparameter、変数を「動的スコープ変数」として宣言します。さらにdefparameter、変数の値は常に、2 番目の引数として渡した値に設定されます。これは とは異なり、defvar以前に設定されていない場合にのみ変数の値を設定します。

setfグローバル レキシカル スコープを使用して、またはグローバル レキシカル スコープ内で変数を定義するsetqことは未定義です。一部の実装では、動的にスコープが設定された変数が作成されますが、作成されない実装もあります。初めて実行するときに、診断メッセージが表示される場合があります。

レキシカル スコープの変数と動的スコープの変数の違いを理解するには、次のコード スニペットを試してください。

* (defvar *a* 1)

*A*
* (let ((*a* 5)) (defun demo-a () *a*))

DEMO-A
* (let ((b 5)) (defun demo-b () b))

DEMO-B
* (let ((*a* 100)) (demo-a))

100
* (let ((b 100)) (demo-b))

5

ここでは、動的スコープの変数と、値を返す関数を作成します (関数の作成中に異なる値を持つバインディング内で定義されます。これは必要ではなく、b に対するレキシカル クロージャと同様に見えるようにするためだけに行われます)。次に、新しい変数を定義し、その値を返す関数を定義します。

その後、値を同じ名前の変数にバインドするクロージャー内で、両方の関数を呼び出します。動的スコープの場合は、同じ変数です。レキシカル クロージャのケース (b) では、2 つの異なるレキシカル クロージャで定義されているため、単に同じ名前を持っていますが、同じ変数ではありません。

setfとの違いに関してはsetq、常に使用するようにしてください(どこで機能し、同じことをしないsetfかの例は考えられません)。(setq blah blahblah)(setf blah blahblah)

于 2012-01-19T14:44:53.490 に答える