Hy语言let-cwd宏中变量b路径赋值错误原因排查
问题:Hy语言let-cwd宏中变量路径赋值错误原因分析
目录结构
. ├── a │ ├── 1 │ ├── 2 │ ├── 3 │ └── 4 ├── b │ ├── 5 │ ├── 6 │ ├── 7 │ └── 8 ├── c ├── d └── test.hy
问题代码
(eval-and-compile (import os) (import pathlib [Path])) (defmacro with-cwd [dir #* body] `(let [ cwd (.cwd Path) ] (try (.chdir os ~dir) ~@body (finally (.chdir os cwd))))) (defmacro let-cwd [dir vars #* body] `(let ~vars (with-cwd ~dir ~@body))) (setv a (/ (. (Path __file__) parent) "a")) (let-cwd a [ b (/ a.parent "b") ] (print f"Hello from {(.cwd Path)}!\n") (print (.resolve b)))
预期输出
Hello from /home/shadowrylander/with-cwd-test/a! /home/shadowrylander/with-cwd-test/b
实际输出
Hello from /home/shadowrylander/with-cwd-test/a! /home/shadowrylander/with-cwd-test/a/b
原因分析
问题出在两个核心点:
路径的相对/绝对属性:
当你以相对路径运行脚本时,__file__是相对路径,导致(. (Path __file__) parent)返回的是相对路径.(即当前工作目录),而非项目根目录的绝对路径。因此a被赋值为相对路径a,a.parent的结果是相对路径.,最终(/ a.parent "b")得到的是相对路径b,不是指向根目录下b的绝对路径。宏执行顺序与Path.resolve()的行为:
你的let-cwd宏展开后,会先完成变量b的赋值(此时工作目录是项目根目录,相对路径b原本指向根目录下的b),再切换到a目录。但Path.resolve()方法会基于当前工作目录解析相对路径,当在a目录下调用.resolve b时,相对路径b会被解析为a目录下的b,而非原本预期的根目录下的b。
解决方法
- 确保路径为绝对路径:在定义
a时就解析为绝对路径,这样后续的路径计算都会基于绝对路径,不受当前工作目录影响:(setv a (.resolve (/ (. (Path __file__) parent) "a"))) - 调整宏结构(按需):如果需要变量赋值依赖切换后的工作目录,可将
let放到with-cwd内部(此场景下非必须,但适用于依赖当前cwd的变量赋值):(defmacro let-cwd [dir vars #* body] `(with-cwd ~dir (let ~vars ~@body)))
内容的提问来源于stack exchange,提问作者syvlorg
相关产品推荐
相关产品推荐

