用于访问整数位的函数的通用Lisp setf展开

问题描述 投票:1回答:1

我正在用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)和状态位...] >

lisp common-lisp
1个回答
0
投票

根据GET-SETF-EXPANSION的SBCL文档,setf扩展器必须:“返回SETF机制所需的五个值:临时列表变量,填充它们的值列表,临时变量列表对于新值,设置功能和访问功能。“

尝试一下:

© www.soinside.com 2019 - 2024. All rights reserved.