Hy准引号宏中隐藏模块辅助函数的可行方案问询
解决方案
要实现导出宏同时隐藏辅助函数的需求,可以通过控制模块导出列表+宏展开时引用模块限定的辅助函数来解决,具体步骤如下:
1. 定义模块导出列表__all__
在a.hy中添加__all__变量,仅将需要导出的宏m列入其中,这样外部模块使用import *或require *时,只会导入m,不会获取到辅助函数_add。
2. 修改宏展开代码,引用模块内的辅助函数
宏展开后的代码需要明确引用模块自身的_add函数,避免依赖调用方的命名空间。可以直接使用模块名限定,或者用current-module动态获取当前模块,避免硬编码模块名。
最终a.hy代码(硬编码模块名版本)
; a.hy (defn _add [x y] (+ x y)) ; 仅导出宏m (def __all__ ["m"]) (defmacro m [x] ; 展开为引用模块a的_add函数 `(a._add ~x 2))
更灵活的版本(动态获取模块)
如果担心模块重命名,可使用current-module动态获取当前模块,避免硬编码:
; a.hy (defn _add [x y] (+ x y)) (def __all__ ["m"]) (defmacro m [x] `((getattr (current-module) '_add) ~x 2))
测试效果(b.hy)
; b.hy (require a *) (print (m 5)) ; => 7,宏正常工作 (print (_add 5 2)) ; => NameError: name '_add' is not defined,符合隐藏预期
原理说明
__all__控制模块的导出范围,外部使用通配符导入时,只会加载__all__中声明的符号,辅助函数_add不会被导入到调用方的命名空间。- 宏展开后的代码直接引用模块自身的
_add函数(通过模块限定名或动态获取模块属性),不需要调用方导入该函数,只要模块a已被加载,就能正常执行。 - 若外部模块主动显式导入
_add(如(import a [_add])),仍能访问,但这属于主动行为,我们的目标是避免默认导出,已达成需求。
内容的提问来源于stack exchange,提问作者Andrii Kozytskyi
相关产品推荐
相关产品推荐

