일반적인 설정 도구는 없지만 SETF를 사용하면 DEFINE-SETF-EXPANDER을 사용할 때 하나를 제공해야합니다. 나는 당신이 lenses/functional references의 등가물을 정의 할 수 있다고 가정합니다. 또 다른 접근 방식으로 Clojure는 update 함수를 정의합니다 (다른 언어에서 빌려 왔지만 Prolog에 있음을 알고 있습니다). FSET 라이브러리는 일부 기능적 구조, 특히 Clojure 에서처럼 작동하는 연관지도를 제공합니다.
잠시 동안 가정 당신은 구조에 자신을 제한 :
(defstruct foo a b c)
(defstruct bar x y z)
(defparameter *test*
(make-foo :a (make-bar :x 0 :y 0 :z 0)
:b 100
:c "string"))
;; *test* is now
;; #S(FOO :A #S(BAR :X 0 :Y 0 :Z 0) :B 100 :C "string")
다음 방법은 사본을 만들고,이 표준은 아니지만 well supported 인, copy-structure
및 slot-value
에 의존 :
(defun update (structure keys value)
(if (endp keys)
value
(destructuring-bind (key &rest keys) keys
(let ((copy (copy-structure structure)))
(setf (slot-value copy key)
(update (slot-value copy key)
keys
value))
copy))))
*test*
을 다음과 같이 업데이트 할 수 있습니다.
(update *test* '(a z) 10)
여기에 추적입니다 :
0: (UPDATE #S(FOO :A #S(BAR :X 0 :Y 0 :Z 0) :B 100 :C "string") (A Z) 10)
1: (UPDATE #S(BAR :X 0 :Y 0 :Z 0) (Z) 10)
2: (UPDATE 0 NIL 10)
2: UPDATE returned 10
1: UPDATE returned #S(BAR :X 0 :Y 0 :Z 10)
0: UPDATE returned #S(FOO :A #S(BAR :X 0 :Y 0 :Z 10) :B 100 :C "string")
당신이 부분적으로 (#'1+
와 결과 폐쇄를 업데이트 기능을 적용하여 incf
에 해당 구현할 수 있도록, 당신이 대신 값의 함수를 받아 들일 수있는 일반화하기 위해, 키의 목록을 수락합니다.
또한 일반 기능에서 가능한 복사본 작업을 일반화해야합니다. 마찬가지로 다른 종류의 접근자를 사용하고 slot-value
을 access
함수 ((setf access)
연산이 있음)로 바꿀 수 있습니다. 그러나 일부 데이터를 공유하려는 경우이 일반적인 복사/설정 방법은 낭비 적이 될 수 있습니다. 예를 들어, 데이터를 이끌어내는 목록의 일부만 복사하면됩니다. 단락 뒤의 단락 셀은 복사 할 필요가 없습니다.
당신은 사용자 정의 업데이터를 정의하는 몇 가지 기능을 정의 할 수 있습니다 : 당신이 상기 CLOS 객체 리더/라이터를 쓴 것처럼
(defmethod perform-update (new (list list) position)
(nconc (subseq list 0 position)
(list new)
(nthcdr (1+ position) list)))
그럼 CLAS 인스턴스를 제외하고 기본 lisp 객체로 복사하는 것을 제한한다고 가정하면 보편적 인 복사 아이디어의 핵심은 기본 객체의 각 유형에 대한 재귀 일반 메소드를 작성하는 것입니다. – davypough
@davypough 예, 기본 범용 복사본은 데이터 구조의 모든 구성 요소의 복사본을 만들 수 있습니다 (단 하나의 복사본 수준 만 필요합니다. 위의 업데이트 함수는 필요한 경우 재귀 복사본을 수행함). 순환 참조에 문제가 있음을 유의하십시오. – coredump