Lisp 没有实际的指针。但是根据fundamental theorem of software engineering,我们可以通过添加一个间接级别来模拟它们。我们可以使用某种容器,例如 cons cell 或 defstruct。
(defstruct pointer
array
offset)
(defun pointer-deref (ptr)
(aref (pointer-array ptr) (pointer-offset ptr)))
(defun set-pointer-deref (ptr value)
(setf (aref (pointer-array ptr) (pointer-offset ptr)) value))
(defsetf pointer-deref set-pointer-deref)
(defvar my-array (vector 1 2 3 4 5 6 7 8 9 10))
(defvar my-ptr (make-pointer :array my-array :offset 3))
(print (pointer-deref my-ptr)) ; prints 4
(setf (pointer-deref my-ptr) 20)
(print my-array) ; prints #(1 2 3 20 5 6 7 8 9 10)
(incf (pointer-offset my-ptr))
(print (pointer-defer my-ptr)) ; prints 5
(defvar my-array-2 (vector 15 30 40))
(setf (pointer-array my-ptr) my-array-2 (pointer-offset my-ptr) 0)
(print (pointer-deref my-ptr)) ; prints 15
上面的代码大致类似于这段C代码:
int my_array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int *my_ptr = &my_array[3];
printf("%d\n", *my_ptr);
*my_ptr = 20;
for (int i = 0; i < 10; i++) {
printf("%d ", my_array[i]);
}
my_ptr++;
printf("%d\n", *my_ptr);
int my_array2[] = {15, 30, 40};
my_ptr = &my_array2[0];
printf("%d\n", *my_ptr);
为了与 Lisp 的动态类型保持一致,这些指针可以指向任何类型的数据,您不必声明类型。另一方面,这个实现只支持指向数组元素的指针,而 C 指针也可以指向变量和结构成员。更复杂的实现可以使用 CLOS 来定义不同类的指针,并使用通用函数来允许您一致地使用它们。这也可以解决 C 中的一些指针安全问题;他们可以检查偏移量是否在范围内,防止增加不指向数组元素的指针等。