在Clojure中对象层次结构中的子对象上重复出现

在Clojure中对象层次结构中的子对象上重复出现,clojure,Clojure,我有以下问题: (def relations1 '((child-of peter carl) (child-of carl herb) (peter x 0 y 0 age 6) (carl x 1 y 1 age 36) (herb x 2 y 2 age 66))) 如果父对象移动,则子对象将移动相同的距离,因此如果新关系声明herb和peter已移动,则我希望以相同的偏移量更新relation2中不存在的子对象,但那些存在的子对象将不受

我有以下问题:

(def relations1 
  '((child-of peter carl) 
    (child-of carl herb)

    (peter x 0 y 0 age 6) 
    (carl  x 1 y 1 age 36) 
    (herb  x 2 y 2 age 66)))
如果父对象移动,则子对象将移动相同的距离,因此如果新关系声明herb和peter已移动,则我希望以相同的偏移量更新relation2中不存在的子对象,但那些存在的子对象将不受影响。因此,在下一阶段:

(def relations2 
  '((herby2 x 3 y 2.5 age 66) 
    (pete2  x 0 y 0   age 6)))
我首先将关系1与关系2中的关系匹配:

(def matches 
  '( ((herb x 2 y 2 age 66) 
      (herb2 x 3 y 2.5 age 66)), 

     ((peter x 0 y 0 age 6)
      (peter2 x 0 y 0 age 6))))
我想检查匹配的人,更新他们自己的新位置(同时保留他们以前的姓名和年龄),并递归检查他们是否有孩子更新他们的位置。我试过了,但也被困在如何在孩子们身上重现的问题上:

(def update-parents [matches, relations1]
(loop [rest matches
       all relations1
       result ()]
 (if (empty? rest)
     result
     (let [[head & others] rest
            r1 (first head)
            r2 (second head)
            exists (map first r2)
            children (map second (filter #(and (= (first r1) (last %)) (= 'child-of (first %))) all))] 
          (if (some #(= (first r1) %) exists)
               (recur others (concat (update r1 r2) (recur ???)); if it is already there, update position and its children's
               ; if it's not there, then ignore

) 
所以最终的结果应该是这样

(def result 
  '((herb  x 3 y 2.5 age 66)
    (peter x 0 y 0   age 6) 
    (carl  x 2 y 1.5 age 36) ))
我有两个主要问题:

  • children返回一个子项列表,因此我需要按列表中的子项筛选关系1
  • 我如何在孩子身上复发?我需要使用另一个循环吗

  • 您可以通过将要删除的内容放入一个集合并使用
    (删除#(包含集合%)列表)
    或更惯用的
    (删除集合列表)
    从列表中删除内容(即创建一个没有这些内容的新列表),因为集合作为一个函数运行。(“过滤”的作用类似,但保留谓词同意的内容。)

    循环
    重复
    特殊形式将仅从尾部位置重复,这可能是对给定问题的挑战。但如果您不需要尾部调用优化,那么函数可以简单地调用自身

    在任何情况下,如果要使用任何类型的递归,都需要一个树形数据结构,其中每个节点都类似于根。
    关系1
    中的“事实袋”将很难处理

    查看
    clojure.walk
    clojure.zip
    作为树数据结构的固定解决方案


    另外,以“自下而上”的方式在REPL中工作也可能会有所帮助,可以在砂锅菜之前处理配料。

    您可能对处理树状数据结构的Tupelo Forest库感兴趣:谢谢!但是为了得到
    集合
    ,我需要先做一个过滤器,对吗?此外,我是否应该维护一个树,在其中遍历最新的关系集,并首先使用“关系的子对象”更新树,以便更容易找到它们的子对象?
    (删除列表中的集合)
    似乎不适用于例如
    (定义集合(pete jo))(定义列表(alvin))
    它给了我一个错误
    clojure.lang.PersistentList无法转换为类clojure.lang.IFn
    我发现了它是如何工作的,您需要将它放入
    (删除(设置)列表)
    才能工作: