我正在用Common Lisp编写一个程序,该程序需要为一阵列中的大量条目存储一堆状态位(整个程序几乎都是fortran-in-lisp),并且状态位被编码为位在这个数组中的一个fixnum中。这些状态位的访问器实际上将由宏定义,因此我不必关心分配位,但是示例读取器功能可能是
(defun deadp (e)
(logbitp 0 e))
((在现实生活中,这会用声明进行内联和混乱,以尝试确保它很快,但是我认为此处无关紧要。)
我需要这些东西作为函数,因为我希望能够将它们映射,还因为使用宏到函数的内联函数使我感到难受。
然后我将使用它作为类似这样的内容:
(defconstant status-index 3)
...
(dotimes (i nentries)
(unless (deadp (aref entries i status-index))
...))
((在现实生活中,(aref entries i status-index)
将是(status entries i)
,这又将需要setf
方法,但我认为这很容易。)
或
(loop for i below nentries
counting (if (deadp entries i status-index) 1 0))
当然,还有其他类似的单一位标志,它们具有与之相关的不同位。
所以,现在我希望能够做到这一点:
(dotimes (i nentries)
...
(when ...
(setf (deadp (aref entries i status-index) t)))
...)
应该变成与之等效的代码
(dotimes (i nentries)
...
(when ...
(progn
(setf (ldb (byte 1 0) (aref entries i status-index)) 1)
t))
...)
还有这个:
(let ((status 0))
...
(when ...
(setf (deadp status) t))
...)
应该变成与此等效的代码:
(let ((status 0))
...
(when ...
(progn
(setf (ldb (byte 1 0) status) 1)
t))
...)
换句话说,我希望我的deadp
函数成为访问器,并希望其上的setf
以常规方式起作用:(setf (deadp (cdr x)) nil)
应该起作用,等等。>
因此,这使我陷入了很长一段时间以来我一直避免的CL位中:定义setf
扩展器。很明显,仅定义(setf deadp)
函数将不起作用,因为数字是不可变的,而且我相当
defsetf
不够强大,所以我需要define-setf-expander
,我不明白。有人可以解释我该怎么做吗?我认为特定的deadp
函数并不重要,尽管我关心的所有函数看起来都像是它的变体。
另一种选择是'这是一种死脑筋的方法,而是...。而我对此持开放态度。我考虑过编写将数组抽象化的代码,所以我会写(deadp (aref ...))
而不是(deadp people ...)
,其中people
是人的数组。很好,很容易看出如何使setf
可用,除了我也想说(deadp status)
,其中status
只是一个Fixnum。但是也许有更好的方法。
我用Common Lisp编写了一个程序,该程序需要为阵列中的大量条目存储一堆状态位(整个程序几乎都是fortran-in-lisp)和状态位...] >
根据GET-SETF-EXPANSION的SBCL文档,setf扩展器必须:“返回SETF机制所需的五个值:临时列表变量,填充它们的值列表,临时变量列表对于新值,设置功能和访问功能。“
尝试一下: