为什么SBCL(或Common Lisp)下我写的loop版本目录向上查找函数编译报错
问题原因及修复方案
你的find-dir-upwards-loop存在两个核心问题:
- 逻辑错误:
loop的with子句只会在循环启动前一次性求值,你代码里的f永远是初始dir参数和marker-file拼接的结果,不会跟随curr的迭代更新,哪怕编译通过也找不到子目录里的标记文件。 - 类型不匹配错误:变量
prev的初始值为nil(空类型),后续迭代会被赋值为路径类型的curr,SBCL的严格类型推断检测到同一个变量持有两种不兼容类型,因此抛出编译错误。
修复后的实现
推荐直接调整终止条件写法,不需要prev变量,从根源避免类型冲突,同时把标记文件路径的计算放到循环体内每次执行,和你的递归实现逻辑完全等价:
(defun find-dir-upwards-loop (dir marker-file) (loop for curr = dir then parent for parent = (uiop:pathname-parent-directory-pathname curr) for f = (merge-pathnames marker-file curr) when (uiop:file-exists-p f) return curr until (equal curr parent)))
如果一定要保留prev的写法,需要给prev加兼容类型注解,同时把f的计算移到循环体:
(defun find-dir-upwards-loop (dir marker-file) (declare (type pathname dir)) (loop for prev of-type (or null pathname) = nil then curr for curr of-type pathname = dir then (uiop:pathname-parent-directory-pathname curr) until (equal curr prev) for f = (merge-pathnames marker-file curr) when (uiop:file-exists-p f) return curr))
内容的提问来源于stack exchange,提问作者MrDispatch
相关产品推荐
相关产品推荐

