是否可在Clojure的ns声明中插入自定义Require表单?
能否在Clojure的
ns命名空间声明中插入自定义表单? 可以实现,但原生ns宏默认不支持直接识别和:require同级的自定义子句,需要做一层宏层面的定制处理。
- 原生
ns宏有固定的合法子句白名单,只认:require、:use、:import、:refer-clojure、:gen-class这几个内置前缀的子句,直接写你示例里的:refer-my-library会触发编译报错,因为宏展开阶段找不到对应处理逻辑。
最稳妥的实现方案
自己写一层包装ns的自定义宏,先预处理所有传入的子句,把自定义子句转换成原生ns能识别的标准配置,再把剩下的内置子句透传给原生ns执行即可。
最简实现示例:
(defmacro my-ns [ns-name & clauses] (let [{custom-clauses true standard-clauses false} (group-by #(= :refer-my-library (first %)) clauses) ;; 在这里写自定义子句的转换逻辑 converted-clauses (mapcat (fn [[_ & opts]] ;; 示例逻辑:自动引入目标库,透传exclude等配置 `((:require [com.your.library.core :refer :all ~@opts]))) custom-clauses)] `(clojure.core/ns ~ns-name ~@converted-clauses ~@standard-clauses)))
使用时就能达到你要的写法效果:
(my-ns demo.core (:refer-my-library :exclude [something]) (:require [x :as y]))
注意事项
不要直接修改
clojure.core/ns的原生实现,这种全局修改会污染所有命名空间的声明逻辑,很容易和第三方库产生难以排查的兼容性问题。
不建议依赖Clojure内部未公开的ns扩展钩子注册自定义子句,这类内部API没有稳定性承诺,跨版本升级大概率失效。
内容的提问来源于stack exchange,提问作者Scott Klarenbach
相关产品推荐
相关产品推荐

