임의의 글로벌 변수를 돌연변이하기 위해 기능 라이브러리 생성

StackOverflow https://stackoverflow.com/questions/20353946

  •  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

당신은 왜 제거하지 않습니까? set-global 완전히 기능하고 모든 기능이 전역 변수를 동일한 스타일로 전달하기를 원한다면 모두 사용하도록하십시오. symbol-value 따라서 이러한 기능을 사용하는 사람은 누구나 어떤 DO를 알 필요가 없으며 글로벌 변수 이름 앞에서 인용이 필요한지 알 필요가 없습니다. 훨씬 쉬운가요?

다른 팁

이것은 나쁜 스타일과 시간 낭비입니다.

  1. push-something 동일합니다 cons.

  2. push-cdr ~이다 ~ 아니다 기능적 : 인수를 내내 수정하거나 오류가 발생하여 실패합니다. nil 논쟁.

글로벌 변수의 값을 변경하려면 setf 명시 적으로 훨씬 명확합니다.

복잡한 방식으로 글로벌 값의 내부를 수정하려면이를 위해 특수 함수를 작성해야 할 수도 있지만 해당 기능은 전 세계 변수에 바인딩 된 값을 대조적으로 수정한다는 사실에 대한 불가지론이어야합니다. 어휘 변수.

요컨대, 두 가지 별도의 직교 문제가 있습니다 - 글로벌 변수 변경 (사용 setq) 및 대상의 내부를 변화시킨다 (글로벌 성격의 불가지론 적).

추신. "Setf가 함수 내부에있을 때 글로벌 변수의 값을 변경하지 않는다"는 것이 확실하지 않습니다.

(defvar *foo* 10)
*FOO* ==> 10
(defun change-foo (x) (setq *foo* x))
(change-foo 123)
*foo* ==> 123
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top