답변:
원래 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의 후속 계승자들로부터 부팅 될 것입니다.
f
사실을 의미 기능 이 아닌 필드 (또는 양식 필드의 setf의 몇 가지 의미가 동안이 정확하지 않을 수 있습니다처럼, 그 문제에 대한) 및 참조를 제공합니다 그래서, 그것은 보인다.
set
함수입니다. 따라서 환경을 모릅니다. set
어휘 변수를 볼 수 없습니다. 인수의 기호 값만 설정할 수 있습니다. setq
더 이상 "인용 설정"되지 않습니다. setq
매크로가 아닌 특별한 형태 라는 사실이 그것을 보여줍니다.
(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 ls '(((1))))
, (setf (car (car (car ls))) 5)
값을 정의하기 때문에 문제가된다 ls
상수 (C 문자열의 문자를 수정하는 등)이다. 후 (setq ls (list (list (list 1))))
, (setf (car (car (car ls))) 5)
단지처럼 작동 ls->val->val->val = 5
C.에서
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
대신에 set
나 setq
아닌 그 반대 때문에이 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
로 확장되는 것처럼 생각할 수 있습니다 .SET
SETQ
* (macroexpand '(setf (symbol-value 'a) 10))
(SET 'A 10)
* (macroexpand '(setf a 10))
(SETQ A 10)
그래서 SET
와 SETQ
의 기능의 일부 구현하는 데 사용됩니다 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))