(defstruct (mydate (:constructor make-mydate (year month day)))
(year 1970)
(month 1)
(day 1))
(defvar *date1* (make-mydate 1992 1 1))
这个问题更普遍,但假设我想将像 date1 这样的对象转换为我可以持久保存到数据库的“文档”(例如 mongoDB,使用包 cl-mongo)。所以我写
(defun mydate->document (mydate)
(cl-mongo:$ (cl-mongo:$ "year" (mydate-year mydate))
(cl-mongo:$ "month" (mydate-month mydate))
(cl-mongo:$ "day" (mydate-day mydate))))
REPL--> (mydate->doc *date1*)
kv-container : #(#S(CL-MONGO::PAIR :KEY year :VALUE 1992)
#S(CL-MONGO::PAIR :KEY month :VALUE 1)
#S(CL-MONGO::PAIR :KEY day :VALUE 1))
但是我可以不用写下我的结构的所有字段,而是以编程方式获取它们的名称和值吗?毕竟,我的 lisp 运行时可以做到这一点:
REPL--> (describe *date1*)
#S(MYDATE :YEAR 1992 :MONTH 1 :DAY 1)
[structure-object]
Slots with :INSTANCE allocation:
YEAR = 1992
MONTH = 1
DAY = 1
另一方面,我没有在任何书中找到任何相关内容,而且我注意到库 cl-json 不能将结构转换为 JSON 格式(即使它确实转换列表和 CLOS 对象)。我想如果有一个将结构体转换成plist的函数,问题就迎刃而解了。
最佳答案
没有可移植的方式。
实现方式不同。可能大多数都有办法访问插槽的名称。我不清楚为什么标准中缺少此类功能。
例如 LispWorks 有:
(structure:structure-class-slot-names (find-class 'some-structure-class))
也许某处已经有一个兼容性库。将 CLOS 的元对象协议(protocol)功能也用于结构类是有意义的。
SBCL:
* (sb-mop:class-slots (find-class 'foo))
(#<SB-PCL::STRUCTURE-EFFECTIVE-SLOT-DEFINITION A>
#<SB-PCL::STRUCTURE-EFFECTIVE-SLOT-DEFINITION B>)
* (mapcar 'sb-mop:slot-definition-name *)
(A B)
关于common-lisp - 常见的 LISP : convert (unknown) struct object to plist?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22084260/