了解Common Lisp aref行为

Run*_*ine 4 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)
Run Code Online (Sandbox Code Playgroud)

Dir*_*irk 9

setf运营商实际上是一个宏,它需要能够在编译时已经检查的地方形式.它有特殊的知识aref,但对你的一无所知ret-aref.

让你的函数知道的最简单方法setfsetf为它定义一个合适的函数伴侣.例:

(defun (setf ret-aref) (new-value array index) 
   (setf (aref array index) new-value))
Run Code Online (Sandbox Code Playgroud)

现在,(setf (ret-aref arr 0) 'bar)应该工作.

这个简单的例子隐藏了这样setf一个事实:-expansion实际上是一个非常多毛的话题.您可以在CLHS中找到血腥细节.