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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 18:52:45