IT

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

lottoking 2020. 6. 6. 21:10
반응형

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)

So SET and SETQ are used to implement some of the functionality of SETF, which is the more general construct. Some of the other answers tell you the slightly more complex story, when we take symbol macros into account.


I would like to add to previous answers that setf is macro that call specific function depending on what was passed as its first argument. Compare results of macro expansion of setf with different types of arguments:

(macroexpand '(setf a 1))

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

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

For some types of arguments "setf function" will be called:

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

참고URL : https://stackoverflow.com/questions/869529/difference-between-set-setq-and-setf-in-common-lisp

반응형