Lisp树形嵌套列表遍历的优雅编码问询及更新函数验证
问题分析与更新函数的正确性验证
首先得说,你遇到的这个问题太典型了——用紧凑格式写树形结构(A (B 1 (2 f g)) C (D 3 4) E)本来很直观,但原有的top-level-elm函数非要每个顶层元素都套一层括号(比如((A) (B 1 (2 f g)) (C) (D 3 4) (E))),不仅写起来麻烦,后续遍历子节点还容易踩类型错误的坑,比如你碰到的The value 3 is not of type LIST,就是因为把原子当成列表来处理了。
接下来看你参考@coredump的答案更新后的top-level-elm函数:
(defun top-level-elm (tree) (loop for i from 0 to (- (length tree) 1) collect (elt (elt (normalize-tree tree) i) 0)))
这个函数的正确性完全取决于normalize-tree的实现——它的核心作用应该是把紧凑的树形结构自动转换成“每个节点都被包裹成单元素列表”的标准化格式(比如把原始树转成((A) ((B) (1) ((2) (f) (g))) (C) ((D) (3) (4)) (E)))。如果normalize-tree能准确完成这个转换,那你的top-level-elm是完全正确的,理由如下:
- 第一步
(normalize-tree tree)把原始的紧凑树转换成了节点全为列表的标准结构; - 第二步
(elt (normalize-tree tree) i)取出第i个顶层节点的列表; - 第三步取这个列表的第一个元素
(elt ... 0),就得到了每个顶层节点的标识(A、B、C、D、E)。
举个实际测试场景:
假设normalize-tree工作正常,执行:
(top-level-elm '(A (B 1 (2 f g)) C (D 3 4) E))
会得到预期结果(A B C D E),和原函数处理冗余格式的效果一模一样,但再也不用手动给单元素节点加括号了,完美解决了格式冗余的问题。
另外,给你个小优化建议,把loop换成更符合Lisp风格的写法,代码会更简洁:
(defun top-level-elm (tree) (mapcar #'car (normalize-tree tree)))
这个写法和你原来的loop实现逻辑完全一致,但可读性更强,也更简洁。
内容的提问来源于stack exchange,提问作者Sati
相关产品推荐
相关产品推荐

