Lisp 修改plist内部列表?

Lisp 修改plist内部列表?,lisp,common-lisp,sbcl,Lisp,Common Lisp,Sbcl,我有一个列表,其中包括 '((:atom Toddler :visited nil :on-clauses (0 1)) (:atom Child :visited nil :on-clauses 1)) 如何更改给定的:atom上的:onclauses属性?我想更新此属性,例如制作第二个plist(:atom Child:visted nil:on子句(12))(仅添加新值,从不删除旧值) 我所能做的就是使用 (remove-if-not #'(lambda(record)

我有一个列表,其中包括

'((:atom Toddler :visited nil :on-clauses (0 1))
  (:atom Child   :visited nil :on-clauses 1))
如何更改给定的
:atom
上的
:onclauses
属性?我想更新此属性,例如制作第二个plist
(:atom Child:visted nil:on子句(12))
(仅添加新值,从不删除旧值)

我所能做的就是使用

(remove-if-not #'(lambda(record)
                   (equal (getf record :atom) atom))
               *ATOMS*)
要获得初始值,请更新它,然后使用其类似项获得一个没有此值的列表,并将两者附加在一起,但这可能是非常不够的(我知道过早优化是不好的,但我正在学习LISP,希望知道如何正确操作!)

使用特定的
:atom
查找plist,然后从plist中删除属性

(defun update-on-clauses (atom new-on-clause)
  (let ((pos (position atom *atoms* 
                       :key #'(lambda (record) (getf record :atom)))))
    (when pos
      (setf (getf (nth pos *atoms*) :on-clauses) new-on-clause))))
使
*ATOMS*
成为将原子映射到属性列表的列表可能更简单。

用于查找具有特定
:atom
的plist,然后从该plist中删除属性

(defun update-on-clauses (atom new-on-clause)
  (let ((pos (position atom *atoms* 
                       :key #'(lambda (record) (getf record :atom)))))
    (when pos
      (setf (getf (nth pos *atoms*) :on-clauses) new-on-clause))))

使原子*成为一个将原子映射到属性列表的列表可能更简单。

这三个函数似乎起到了作用,因为plists被破坏性地修改了

(defun update-atom(atom ix)
  "adds to the atom's on-clauses property another clause where it was found."
   (let ((atomo (find-atom atom)))
    (setf (getf atomo :on-clauses) (cons ix (get-indices atom)))))

(defun find-atom(atom)   "returns the property list of a given atom"   
  (first (remove-if-not #'(lambda(record) (equal (getf record :atom) atom)) *ATOMS*)))

(defun get-indices(atom)
  "gets indices of clauses where atom is found."
  (getf (find-atom atom) :on-clauses))

这三个函数似乎起到了作用,因为plists被破坏性地修改了

(defun update-atom(atom ix)
  "adds to the atom's on-clauses property another clause where it was found."
   (let ((atomo (find-atom atom)))
    (setf (getf atomo :on-clauses) (cons ix (get-indices atom)))))

(defun find-atom(atom)   "returns the property list of a given atom"   
  (first (remove-if-not #'(lambda(record) (equal (getf record :atom) atom)) *ATOMS*)))

(defun get-indices(atom)
  "gets indices of clauses where atom is found."
  (getf (find-atom atom) :on-clauses))

嘿@Barmar,谢谢你的回答!这似乎不是我想要的,我一定写得很糟糕。我发现我这样做其实是太过分了;由于plists被破坏性地改变,只要
setf
ing我从我所写的内容中得到的列表,就会使
*atoms*
列表成为我想要的方式!我在你的代码中看到了
如果不删除就删除
,所以我以为你想删除该属性。我已经更新了我的答案。您的版本不一定有效,因为getf的setf可以简单地分配给局部变量
atomo
,而无需修改全局变量
*atoms*
中的列表。嘿@Barmar,谢谢您的回答!这似乎不是我想要的,我一定写得很糟糕。我发现我这样做其实是太过分了;由于plists被破坏性地改变,只要
setf
ing我从我所写的内容中得到的列表,就会使
*atoms*
列表成为我想要的方式!我在你的代码中看到了
如果不删除就删除
,所以我以为你想删除该属性。我已经更新了我的答案。您的版本不一定有效,因为getf的setf
可以简单地分配给局部变量
atomo
,而无需修改全局变量
*atoms*
中的列表。请注意,您不应该修改引用的文本数据。影响尚未定义。要么使用非破坏性操作,要么复制之前的树。你有什么参考资料我可以读到这个@RainerJoswig吗?我是LISP的新手。请注意,您不应该修改引用的文字数据。影响尚未定义。要么使用非破坏性操作,要么复制之前的树。你有什么参考资料我可以读到这个@RainerJoswig吗?我对LISP相当陌生。您可以使用
(find-atom*atoms*:key(lambda(record)(getf-record:atom))
而不是
find-atom
。另外,
(setf(getf…(cons-ix…)
可以简化为
(push-ix(getf…)
,这使得
获取索引的功能变得不必要。感谢您的提示,@jkiiski!我不知道我可以用那种方式找到。。。虽然我不确定我是否理解它是如何工作的。它使用atom将lambda函数应用于atoms中的每个列表,并返回具有非空值的列表?至于你的第二个建议,我不确定它是否符合我的要求,我会尽快尝试!
FIND
*ATOMS*
中的每个对象调用键函数(此处返回
:ATOM
属性的值),并将返回值与第一个参数(
ATOM
)进行比较。返回键为
EQL
ATOM
的第一个对象。太好了,谢谢@jkiiski!我现在明白了。至于第二个建议,我似乎无法做到这一点:
(push 1(getf'(:atom Child:on子句(02)):on子句))
。这就是您的意思吗?尝试将
(setf…
表单替换为
(push ix(getf atomo:on子句))
。您可以使用
(find atom*atoms*:key(lambda(record)(getf record:atom))
而不是
find-atom
。另外,
(setf(getf…(cons-ix…)
可以简化为
(push-ix(getf…)
,这使得
获取索引的功能变得不必要。感谢您的提示,@jkiiski!我不知道我可以用那种方式找到。。。虽然我不确定我是否理解它是如何工作的。它使用atom将lambda函数应用于atoms中的每个列表,并返回具有非空值的列表?至于你的第二个建议,我不确定它是否符合我的要求,我会尽快尝试!
FIND
*ATOMS*
中的每个对象调用键函数(此处返回
:ATOM
属性的值),并将返回值与第一个参数(
ATOM
)进行比较。返回键为
EQL
ATOM
的第一个对象。太好了,谢谢@jkiiski!我现在明白了。至于第二个建议,我似乎无法做到这一点:
(push 1(getf'(:atom Child:on子句(02)):on子句))
。这就是你的意思吗?试着用
(push ix(getf atomo:on子句))
替换
(setf…
表单。