对有限页面集合做差集[#125]

miniKanren的=/=表示两个项不相等,并不表示“某个关系中不存在匹配行”。这里先查询所有被link或transclude的页面ID,再用递归的not-membero检查一个页面ID不在该有限列表中:

(define-relation (not-membero value values)
    (either
      ((== '() values))
      ((exists (head tail)
         (== `(,head . ,tail) values)
         (=/= value head)
         (not-membero value tail)))))

  (define-relation (authored-pageo page-data page-id title)
    (exists (metadata)
      (pageo page-data
             (page-id page-id)
             (title title)
             (metadata metadata))
      (project (metadata)
        (if (assq-ref metadata 'inline-subtree) fail succeed))))

  (define-relation (orphan-pageo page-data incoming-page-ids page-id title)
    (authored-pageo page-data page-id title)
    (not-membero page-id incoming-page-ids))

authored-pageo通过pageo排除inline subtree自动生成的页面。这样列出的都是项目中的文章页面,而不是正文里可独立寻址的小节。结果里的链接使用查询专用节点,不会被误记为文章作者创建的入链。