Ant*_*ana 4 variables reference common-lisp variable-assignment let
setfwhen 与 结合的行为let让我感到困惑。在这里,setf不会更改列表中的第二个值。
(defun to-temp-field (lst)
(let ((old-value (nth 2 lst))
(new-value 'hello))
(progn
(setf old-value new-value)
lst)))
Run Code Online (Sandbox Code Playgroud)
但如果我不这样做let,它会改变:
(defun to-temp-field (lst)
(let ((new-value 'hello))
(progn
(setf (nth 2 lst) new-value)
lst)))
Run Code Online (Sandbox Code Playgroud)
是什么导致了这种行为?
setf接受一个位置和一个值,或多个位置/值对,并将位置的值更改为新值。
第一个代码示例old-value是绑定在表单内的词法变量let。词法变量是位置,因此调用将设置to(setf old-value new-value)的值。old-valuenew-value
函数形式也可以是地方,并且nth是一个可以指定地点的函数。在第二个代码示例中,调用(setf (nth 2 lst) new-value)将 place 的值设置(nth 2 lst)为 value new-value。
old-value因此,在第一个示例中,词法变量place被更新。但在第二个示例中,表单(nth 2 lst)是一个位置,并且该表单求值的对象(列表的元素lst)被更新。
需要明确的是:地点不是一种价值,而是一种形式。
With(let ((old-value (nth 2 lst)) ;;...)) old-value绑定到表单计算的值(nth 2 lst)。但随着(setf (nth 2 lst) new-value)形式被解释为一个地方。 其工作原理相同:是一种形式,也是一个地方。这里,变量已被 let-bound 绑定到表单 的值,并且通过改变 的绑定,通过调用中的赋值来替换该值。结果,该地方的价值发生了变化。(nth 2 lst)(setf old-value new-value)old-valueold-value(nth 2 lst)setfold-valueold-value
有几点需要注意:
第二个示例更新了 的第三个元素,lst因为列表在 Common Lisp 中是零索引的。
由于表单的主体是隐式的,因此不需要progn内部的表单。letletprogn
尝试修改文字会导致 Common Lisp 中出现未定义的行为,因此您不应该使用这样的带引号列表来调用第二个函数:(to-temp-field '(1 2 3))或使用绑定到列表文字的变量,而是像这样:(to-temp-field (list 1 2 3))或使用绑定到 a 的变量以其他方式构建的列表。
| 归档时间: |
|
| 查看次数: |
212 次 |
| 最近记录: |