You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

未定义的Hy宏执行断言报AssertionError而非NameError,是否为Bug?

关于Hy中未定义宏调用的报错差异问题

先看这段注释掉宏定义的Hy代码:

(eval-and-compile (import os hy))
(eval-and-compile (import pathlib [Path]))
; (defmacro with-cwd [dir #* body]
;           (setv cwd (hy.gensym))
;           `(let [ ~cwd (.cwd Path) ]
;                 (try (.chdir os ~dir)
;                      ~@body
;                      (finally (.chdir os ~cwd)))))
(setv cookies (/ (.cwd Path) "cookies"))

; 此调用触发`AssertionError'
(with-cwd cookies (assert (= (.cwd Path) cookies)))

; 此调用触发`NameError'
(with-cwd cookies (.cwd Path))

调用未定义的with-cwd时出现两种不同报错:第一个调用触发AssertionError,第二个触发NameError,你原本预期第一个也会触发NameError,疑惑这是Bug还是对执行顺序的理解偏差。

原因分析

这不是Bug,核心在于Hy的宏编译特性和assert的特殊形式优先级:

  • 宏的编译时特性:Hy的宏是编译阶段展开的,未定义的宏调用不会被编译器处理,会原封不动传递给Python解释器。
  • assert是特殊形式:和普通函数不同,assert的内部表达式会被优先编译执行。第一个调用中,(= (.cwd Path) cookies)会先被执行——此时工作目录并未切换(with-cwd宏没展开,切换逻辑根本没执行),所以判断结果为假,直接触发AssertionError。这个报错发生在Python尝试处理断言时,还没轮到解析外层的with-cwd符号,因此不会出现NameError。
  • 第二个调用的逻辑:(with-cwd cookies (.cwd Path))没有特殊形式嵌套,Python解释器会直接把with-cwd当作函数名,但这个符号从未定义,所以抛出NameError。

类似地,任何依赖未定义宏的代码,若嵌套了特殊形式,都可能因特殊形式的优先执行提前报错,掩盖宏未定义的问题。

内容的提问来源于stack exchange,提问作者syvlorg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 07:45:51