了解Common Lisp aref行为

时间:2012-12-19 19:34:13

标签: lisp common-lisp

我不明白为什么setf不能用于函数调用返回的数组引用。在下面的例子中,为什么最后的调用会失败?

(setf arr #1a(a b c))

(defun ret-aref (a i)
    (aref a i))

(eql (ret-aref arr 0) (aref arr 0))

;succeeds
(progn
    (setf (aref arr 0) 'foo)
    arr)

;fails
(progn
    (setf (ret-aref arr 0) 'bar)
    arr)

1 个答案:

答案 0 :(得分:9)

setf运算符实际上是一个宏,它需要能够在编译时检查位置表单。它具有关于aref的特殊知识,但对您的ret-aref一无所知。

使setf知道函数的最简单方法是为其定义合适的setf - 函数伴随。例如:

(defun (setf ret-aref) (new-value array index) 
   (setf (aref array index) new-value))

现在,(setf (ret-aref arr 0) 'bar)应该有效。

这个简单的例子隐藏了这样一个事实:setf - 扩展实际上是一个非常多毛的话题。你可以找到血腥的详细信息in the CLHS