如果结果只是 t 或 nil 就足够了,您也可以这样做:
(defun node-in-tree (node tree &key (test #'eql))
(eq t (mapcar (lambda (x) (if (listp x)
(when (node-in-tree node x) (return-from node-in-tree t))
(when (funcall test node x) (return-from node-in-tree t))))
tree)))
这里的诀窍是,一旦出现(funcall test node x) 的阳性情况,return-from 就可以设法从 mapcar 中的 lambda 突破。因此,确保该功能在找到节点后立即停止其调查。
(eq t ...) 是必要的,因为mapcar 返回的列表只要不是 '() 就会被解释为 true,尽管它可能仅包含 nils 作为元素。
好的,我明白了,当使用(map nil ...) 而不是@ignisvolens 所做的(mapcar ...) 时,可以摆脱(eq t ...):
(defun node-in-tree (node tree &key (test #'eql))
(map nil (lambda (x) (if (listp x)
(when (node-in-tree node x) (return-from node-in-tree t))
(when (funcall test node x) (return-from node-in-tree t))))
tree)))
稍微优雅一点的是mapcan
(nil nil nil ...) 作为mapcar 或(map nil ...) 的结果
只是一个'()。
(defun node-in-tree (node tree &key (test #'eql))
(mapcan (lambda (x) (if (listp x)
(when (node-in-tree node x) (return-from node-in-tree t))
(when (funcall test node x) (return-from node-in-tree t))))
tree))))
lambda函数可以概括为:
最终解决方案
(defun node-in-tree (node tree &key (test #'eql))
(mapcan (lambda (x) (when (or (and (listp x) (node-in-tree node x))
(funcall test node x))
(return-from node-in-tree t)))
tree))
或者也不错:
(defun node-in-tree (node tree)
(if (atom tree)
(eql node tree)
(mapcan #'(lambda (x) (if (node-in-tree node x) (return-from node-in-tree t)))
tree)))