2024 年 Clojure 状态调查!中分享您的想法。

欢迎!请参阅关于页面以了解更多关于如何使用本站的信息。

+1
in ClojureScript by

问题描述

编写 clojurescript 宏的作者没有符号到 var 解析的功能。也就是说,在宏展开时期将符号扩展为其完全限定形式。

+     ;; -> cljs.core/+
s/def ;; -> cljs.spec.alpha/def

在 JVM 中,这当然是一个可能。

在 cljs 中,没有这样的可能性,至少干净的做法没有。

  • 存在 cljs.core/resolve 宏,但我认为它是针对 cljs 最终代码的,而不是针对 cljs 的宏。
    • 具体来说,cljs.core/resolve 预期一个引用过的符号,这对于宏编写者来说是一个不必要的限制。
  • cljs.core/resolve 返回一个新的 var,而不是原始的 var。这将丢弃用户提供的元数据。
    • 因此,宏编写者无法观察用户提供的元数据以执行宏展开时期的自定义逻辑

请求

使 cljs.core/resolve 更灵活,或者创建一个专门针对宏编写者的独立解析函数

用例

我有一些现有的 JVM 宏,使用 resolve 在宏展开时期,需要迁移到 cljs。也就是说,这个请求来自实际需求。

解决方案

以下函数工作良好,满足了描述的要求。

但是,合理地认为它是在玩 cljs 内部,因此它可能与新的 cljs 发布版不兼容。

(defn cljs-resolve
  [env sym]
  (let [[var meta] (try
                     (let [var (cljs.analyzer/resolve-var env sym (cljs.analyzer/confirm-var-exists-throw))]
                       [var (cljs.analyzer/var-meta var)])
                     (catch Throwable t
                       [(cljs.analyzer/resolve-var env sym) nil]))]
    (some-> var
            :name
            (vary-meta assoc :cljs.analyzer/no-resolve true)
            (vary-meta merge meta))))

2 个答案

+1
by

您的用例是什么,为什么 cljs.anaylzer/resolve-var 不合适?

cljs.analyzer/resolve-var 应该提供您需要的所有信息。它返回一个包含分析器可用的所有信息的映射。它确实有一个 :meta 键。不清楚为什么你在你的实现中要经过所有其他东西。

cljs.core/resolve 实际上只是一个为代码分片添加的辅助函数,甚至在那里使用也是可疑的,不要使用它。在宏中直接调用 cljs.analyzer/resolve-var 是可以的。

by
谢谢托马斯,我会确保检查 `resolve-var`。我没意识到它,.reasonably,我一直认为 `cljs.core/resolve` 是唯一提供的选项。
by
你之所以知道,是因为“工作区”示例中使用了它。可以用宏 &env 和一个符号调用 cljs.analyzer/resolve-var
by
抱歉,是的,我确实使用过(因此意识到了)`resolve-var`。我得到的印象是这只是一个实现细节;我想这不是情况吧?

我记得是通过查阅源代码找到 `resolve-var` 的,而不是在任何文档中找到的。
0 votes
by

你查看过 cljs.analyzer.api/resolve 吗?它比调用 cljs.analyzer/resole-ar 更受欢迎。

...