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

欢迎!请参阅关于页面以了解更多信息。

+1
{alt} ClojureScript

问题陈述

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

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

在JVM中,这确实是可能的。

在cljs中,没有这样的可能性,至少不是整洁的。

  • 存在cljs.core/resolve宏,但我觉得它旨在用于cljs最终代码,而不是针对cljs的宏。
    • cljs.core/resolve期望一个引用的符号,这对于宏作者来说是一个不必要的限制。
  • cljs.core/resolve返回一个新变量,而不是原始变量。这会丢弃用户提供的元数据。
    • 因此,宏作者不能观察到用户提供的元数据以执行宏展开时的自定义逻辑

请求

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

用例

我将一些现有的JVM宏移植到了 cljs,在宏展开时使用了resolve。即,这个请求源于实际需要。

解决方案

以下函数可以正常工作,满足所述要求。

但是,合理地认为它正在玩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
{alt} by

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

cljs.analyzer/resolve-var 应该提供你所需的一切。它返回一个映射,其中包含分析器提供的所有信息。它确实有 :meta 键。不清楚为什么你在实现中需要做所有这些其他的事情。

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

by
感谢托马斯,我将确保检查 `resolve-var`。我对它并不了解,而且出于某种原因一直以为 `cljs.core/resolve` 是唯一提供的东西。
by
你以为你了解它,因为“解决方案”示例使用了它。可以使用宏 &env 和一个符号调用 cljs.analyzer/resolve-var。
by
对不起,是的,我使用了(因此也了解)`resolve-var`。我相信这并不是一个实现细节;对吧?

我记得是通过查看源代码来找到 `resolve-var`,而不是在任何文档中找到它。
0 投票
by

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

...