당신은 왜 제거하지 않습니까? set-global
완전히 기능하고 모든 기능이 전역 변수를 동일한 스타일로 전달하기를 원한다면 모두 사용하도록하십시오. symbol-value
따라서 이러한 기능을 사용하는 사람은 누구나 어떤 DO를 알 필요가 없으며 글로벌 변수 이름 앞에서 인용이 필요한지 알 필요가 없습니다. 훨씬 쉬운가요?
임의의 글로벌 변수를 돌연변이하기 위해 기능 라이브러리 생성
-
25-08-2022 - |
문제
업데이트 : 함수 인수로 전달되는 글로벌 변수를 돌연변이하려는 몇 가지 기능이있는 경우, 일부는 글로벌의 상징 만 전달하여 (목록의 일부를 밀어 넣는 경우와 같이)이 작업을 수행 할 수 있습니다. 그러나 다른 함수는 기호가 전달 될 때 인용되어야하므로 기호 값에 액세스하고 함수에서 setq를 사용하는 데 필요한 외부 변수를 돌연변이 할 수 있습니다. 이 질문은 기본적으로 이러한 기능을 사용자에게 일관된 인터페이스를 만드는 것에 관한 것입니다.
예제는 돌연변이 기능의 작동 방식과 동일한 사용법을 갖는 도우미를 사용하여 다양한 기능의 인터페이스를 간소화하는 방법 :
내 기술의 두 가지 기본 예는 다음과 같습니다.
(defun push-something (global something)
(push something global)
global) ;; not necessary to return it here since the
;; preceding line already does, but doing so
;; for consistency with other functions and clarity
(defun push-cdr (global something)
(push something (cdr global))
global) ;; must return it if I am going to set the
;; dynamic var to the result of this function,
;; because the preceding line doesn't return the
;; entire new result of the variable
;;; "dirty" function for mutating global variable using "clean" functions above:
(defun set-global (fn global &rest values)
(setf (symbol-value global) (apply fn (copy-list (eval global)) values)))
마지막으로, 나는해야한다 eval
그만큼 global
사용하도록 인용되므로 symbol-value
그리고 나서 나는 copy-list
~하도록 하다 global
실수로 직접 돌연변이되지 않습니다 fn
나는 선택한다 (경우와 같이 push-cdr
더 복잡한 기능에서는 사소하지 않을 수 있습니다).
산출:
CL-USER> (defparameter *g2* nil)
*G2*
CL-USER> (set-global #'push-something '*g2* 5)
(5)
CL-USER> *g2*
(5)
CL-USER> (set-global #'push-cdr '*g2* 99)
(5 99)
CL-USER> *g2*
(5 99)
... 그리고 동일한 기능을 사용할 수 있습니다 *g1*
또는 *g3*
액세스 함수를 통해 모든 등 set-global
.
이 스타일이 좋든 나쁜 스타일입니까, 아니면이 기능을 달성하는 훨씬 더 좋은 방법을 놓치고 있습니까?
해결책 2
다른 팁
이것은 나쁜 스타일과 시간 낭비입니다.
push-something
동일합니다cons
.push-cdr
~이다 ~ 아니다 기능적 : 인수를 내내 수정하거나 오류가 발생하여 실패합니다.nil
논쟁.
글로벌 변수의 값을 변경하려면 setf
명시 적으로 훨씬 명확합니다.
복잡한 방식으로 글로벌 값의 내부를 수정하려면이를 위해 특수 함수를 작성해야 할 수도 있지만 해당 기능은 전 세계 변수에 바인딩 된 값을 대조적으로 수정한다는 사실에 대한 불가지론이어야합니다. 어휘 변수.
요컨대, 두 가지 별도의 직교 문제가 있습니다 - 글로벌 변수 변경 (사용 setq
) 및 대상의 내부를 변화시킨다 (글로벌 성격의 불가지론 적).
추신. "Setf가 함수 내부에있을 때 글로벌 변수의 값을 변경하지 않는다"는 것이 확실하지 않습니다.
(defvar *foo* 10)
*FOO* ==> 10
(defun change-foo (x) (setq *foo* x))
(change-foo 123)
*foo* ==> 123