Pointers 公共Lisp中的指针

Pointers 公共Lisp中的指针,pointers,lisp,common-lisp,Pointers,Lisp,Common Lisp,我想保存一个引用(指针),指向保存在另一个变量中的部分数据: (let ((a (list 1 2 3))) (let ((b (car (cdr a)))) ;here I want to set b to 2, but it is set to a copy of 2 (setf b 4)) a) ;evaluates to (1 2 3) instead of (1 4 2) 我可以使用宏,但是如果要在列表中间更改一些数据,那么我将执行很多代码,而且我不是很灵活: (de

我想保存一个引用(指针),指向保存在另一个变量中的部分数据:

(let ((a (list 1 2 3)))
  (let ((b (car (cdr a)))) ;here I want to set b to 2, but it is set to a copy of 2
    (setf b 4))
  a) ;evaluates to (1 2 3) instead of (1 4 2)

我可以使用宏,但是如果要在列表中间更改一些数据,那么我将执行很多代码,而且我不是很灵活:

(defparameter *list* (create-some-list-of-arrays))
(macrolet ((a () '(nth 1000 *list*)))
  (macrolet ((b () `(aref 100 ,(a))))
    ;; I would like to change the macro a here if it were possible
    ;; but then b would mean something different
    (setf (b) "Hello")))

是否可以创建一个变量作为引用而不是副本?

如果您只需要一些语法上的修饰,请尝试:

注意,这完全是编译时的事情。任何地方(在
符号macrolet
的范围内,
b
用作变量时,它在编译时被扩展为
(car(cdr a))
。正如Sylvester已经指出的,CommonLisp中没有“引用”

不过,我不建议一般使用这种做法

顺便说一下:永远不要更改引用的数据。在常量列表文字上使用
(setf(car…)
(及类似)如
”(1 2 3)
,将产生未定义的后果

cl-user> (let ((a '(1 2 3)))
           (let ((b (car (cdr a))))
             (setf b 4))
           a)
;Compiler warnings :
;   In an anonymous lambda form: Unused lexical variable B
(1 2 3)
cons
单元格是一对指针
car
取消对第一个的引用,
cdr
取消对第二个的引用。你的名单是有效的

  a -> [ | ] -> [ | ] -> [ | ] -> NIL
        |        |        |
        1        2        3
在定义
b
的顶部,
(cdr a)
将获得第二个箭头。取下该单元格的
car
,将取消对第二个单元格的第一个指针的引用,并将其值传递给您。在本例中,
2
。如果要更改该指针的值,需要
setf
it而不是它的值

cl-user> (let ((a '(1 2 3)))
           (let ((b (cdr a)))
             (setf (car b) 4))
           a)
(1 4 3)

基于巴格斯的建议。这并不完全是您想要的,但您可以定义setf扩展器来创建“访问器”。因此,假设您的列表包含有关处于for of(姓氏)状态的人的信息,当某人结婚时,您可以将其更新为:

(defun marital-status (person)
  (third person))

(defun (setf marital-status) (value person)
  (setf (third person) value))

(let ((person (list "John" "Doe" "Single")))
  (setf (marital-status person) "Married")
  person)
;; => ("John" "Doe" "Married")

(let((a(list 1 2 3))(setf(second a)4)a有什么问题?我强烈建议阅读本文,重点关注值、变量和位置的细节。如果您不是该语言的新手,很抱歉,但是如果您是,请记住,其他语言的映射技术不一定能为您提供好的或快速的代码。您可能会对讨论C指针、通过结构间接寻址(包括cons单元格)、通用引用、,以及模拟C风格的指针。问题并不完全相同,但我认为答案可能是您所需要的。使用引号定义的列表是常量,修改常量的效果未定义。如果要修改列表,请使用列表创建它
(defun marital-status (person)
  (third person))

(defun (setf marital-status) (value person)
  (setf (third person) value))

(let ((person (list "John" "Doe" "Single")))
  (setf (marital-status person) "Married")
  person)
;; => ("John" "Doe" "Married")