[common-lisp] Common Lisp에서`set`,`setq` 및`setf`의 차이점은 무엇입니까?

Common Lisp에서 “set”, “setq”및 “setf”의 차이점은 무엇입니까?



답변

원래 Lisp에는 어휘 변수가 없었으며 동적 변수 만있었습니다. 그리고 SETQ 또는 SETF는 없었으며 SET 기능 만있었습니다.

이제 다음과 같이 쓰여집니다 :

(setf (symbol-value '*foo*) 42)

로 작성되었습니다 :

(set (quote *foo*) 42)

결국 SETQ (SET 인용)로 축약되었습니다.

(setq *foo* 42)

그런 다음 어휘 변수가 발생했고 SETQ도 할당에 사용되었으므로 SET를 둘러싼 단순한 래퍼가 아니 었습니다.

나중에 다른 언어의 l- 값을 반영하기 위해 데이터 구조에 값을 할당하는 일반적인 방법으로 SETF (SET 필드)를 발명했습니다.

x.car := 42;

로 작성됩니다

(setf (car x) 42)

대칭성과 일반성을 위해 SETF는 SETQ의 기능도 제공했습니다. 이 시점에서 SETQ는 로우 레벨 프리미티브이고 SETF는 하이 레벨 오퍼레이션이라고 말하는 것이 옳았을 것입니다.

그런 다음 기호 매크로가 발생했습니다. 심볼 매크로가 투명하게 작동 할 수 있도록 할당 된 “변수”가 실제로 심볼 매크로 인 경우 SETQ는 SETF처럼 작동해야한다는 것을 깨달았습니다.

(defvar *hidden* (cons 42 42))
(define-symbol-macro foo (car *hidden*))

foo => 42

(setq foo 13)

foo => 13

*hidden* => (13 . 42)

그래서 우리는 현재에 도착합니다. SET과 SETQ는 오래된 방언의 멸망으로 남아 있으며, 아마도 Common Lisp의 후속 계승자들로부터 부팅 될 것입니다.


답변

(set ls '(1 2 3 4)) => Error - ls has no value

(set 'ls '(1 2 3 4)) => OK

(setq ls '(1 2 3 4)) => OK - make ls to (quote ls) and then have the usual set

(setf ls '(1 2 3 4)) => OK - same as setq so far BUT

(setf (car ls) 10) => Makes ls '(10 2 3 4) - not duplicated by setq/set


답변

setq단지처럼 set인용 된 첫 번째 인수와 – (set 'foo '(bar baz))처럼입니다 (setq foo '(bar baz)). setf반면에 실제로는 미묘합니다. “간접”과 같습니다. 나는 제안 http://www.nano.com/lisp/cmucl-tutorials/LISP-tutorial-16.html이 더 좋은 방법은 어떤 대답보다 그것을 이해하기 시작하는 여기에 제공 할 수 있습니다 … 한마디로하지만, setf소요 첫 번째 인수를 “참조”로 사용하여 예를 들어 첫 번째 인수로 (aref myarray 3)작동 setf하여 배열 내부의 항목을 설정합니다.


답변

당신이 사용할 수있는 setf대신에 setsetq아닌 그 반대 때문에이 setf변수가 개별 요소가있는 경우에도 변수의 개별 요소의 값을 설정할 수 있습니다. 아래의 사례를 참조하십시오.

네 가지 예 모두 목록 (1, 2, 3)을 foo라는 변수에 할당합니다.

(set (quote foo) (list 1 2 3))    ;foo => (1 2 3)
(1 2 3)

(set 'foo '(1 2 3))   ;foo => (1 2 3) same function, simpler expression
(1 2 3)

(setq foo '(1 2 3))   ;foo => (1 2 3) similar function, different syntax
(1 2 3)

(setf foo '(1 2 3))   ;foo => (1 2 3) more capable function
(1 2 3)

setf목록의 멤버를 foo새로운 값 으로 설정하는 기능이 추가되었습니다 .

foo                   ;foo => (1 2 3) as defined above
(1 2 3)

(car foo)             ;the first item in foo is 1
1

(setf (car foo) 4)    ;set or setq will fail since (car foo) is not a symbol
4

foo                   ;the fist item in foo was set to 4 by setf
(4 2 3)

그러나 단일 항목을 나타내는 심볼 매크로를 정의 할 수 있습니다. foo

(define-symbol-macro foo-car (car foo))    ; assumes FOO => (1 2 3)
FOO-CAR

foo-car               ;foo-car is now a symbol for the 1st item in foo
1

(setq foo-car 4)      ;set or setq can set the symbol foo-car 
4

foo                   ;Lisp macros are so cool
(4 2 3)

defvar변수를 아직 정의하지 않았고 나중에 코드에서 값을 지정하지 않으려는 경우 사용할 수 있습니다 .

(defvar foo2)
(define-symbol-macro foo-car (car foo2))


답변

저수준 구조를 생각 SET하고 가질 수 있습니다 SETQ.

  • SET 기호 값을 설정할 수 있습니다.

  • SETQ 변수 값을 설정할 수 있습니다.

그런 다음 SETF매크로는 심볼, 변수, 배열 요소, 인스턴스 슬롯 등 다양한 설정 항목을 제공합니다.

기호와 변수의 경우 와 SETF로 확장되는 것처럼 생각할 수 있습니다 .SETSETQ

* (macroexpand '(setf (symbol-value 'a) 10))

(SET 'A 10)


* (macroexpand '(setf a 10))

(SETQ A 10)

그래서 SETSETQ의 기능의 일부 구현하는 데 사용됩니다 SETF더 일반적인 구조입니다. 다른 답변 중 일부는 심볼 매크로를 고려할 때 약간 더 복잡한 이야기를 알려줍니다.


답변

setf는 첫 번째 인수로 전달 된 내용에 따라 특정 함수를 호출하는 매크로라는 이전 답변에 추가하고 싶습니다. 다른 유형의 인수와 setf의 매크로 확장 결과를 비교하십시오.

(macroexpand '(setf a 1))

(macroexpand '(setf (car (list 3 2 1)) 1))

(macroexpand '(setf (aref #(3 2 1) 0) 1))

일부 유형의 인수에 대해서는 “setf function”이 호출됩니다.

(defstruct strct field)
(macroexpand '(setf (strct-field (make-strct)) 1))


답변