【问题标题】:Clojure tools.analyzer, don't expand macrosClojure tools.analyzer,不要展开宏
【发布时间】:2017-07-24 14:02:31
【问题描述】:

使用tools.analyzer.jvm/analyze创建ast时避免扩展宏的最佳方法是什么

这是我目前正在收集的信息的一个示例: (函数名到依赖集的映射)

  {some-function
  #{{:name load-order-ns-file-maps, :ns #namespace[clj-graph.core]}
    {:name *logger-factory*, :ns #namespace[clojure.tools.logging]}
    {:name analyze, :ns #namespace[clojure.tools.analyzer.jvm]}
    {:name make-dir-tracker, :ns #namespace[clj-graph.core]}
    {:name enabled?, :ns #namespace[clojure.tools.logging.impl]}
    {:name read-all, :ns #namespace[clj-graph.core]}
    {:name get-logger, :ns #namespace[clojure.tools.logging.impl]}
    {:name traverse-expr, :ns #namespace[clj-graph.core]}
    {:name log*, :ns #namespace[clojure.tools.logging]}
    {:name track-reload,
     :ns #namespace[clojure.tools.namespace.reload]}
    {:name examine-form, :ns #namespace[clj-graph.core]}}}

实际代码调用log/info,但由于这是宏扩展的,我永远无法捕获声明它的名称和ns - 相反,我得到了宏扩展:

:name *logger-factory*, :ns #namespace[clojure.tools.logging]
:name enabled?, :ns #namespace[clojure.tools.logging.impl]
:name get-logger, :ns #namespace[clojure.tools.logging.impl]
:name log*, :ns #namespace[clojure.tools.logging]

在构建依赖图时,理想情况下我只想找到端点,即:name info :ns #namespace[clojure.tools.logging]

阅读analyzer.jvm/analyze 的文档,它举了一个例子:

(analyze form env {:bindings  {#'ana/macroexpand-1 my-mexpand-1}})

但是当我尝试这个时,即:

(defn ^:dynamic my-expand-1 [form] form)

(ana/analyze
 '(defn prnt [xs] (my-pre-defined-macro xs))
 (ana/empty-env)
 {:bindings  {#'ana/macroexpand-1 my-expand-1}})

我得到了错误

IllegalStateException Can't dynamically bind non-dynamic var:
clojure.tools.analyzer.jvm/macroexpand-1  clojure.lang.Var.pushThreadBindings (Var.java:320)

【问题讨论】:

  • 您找到解决方案了吗?我有完全相同的问题。

标签: dynamic clojure macros analyzer


【解决方案1】:

如果宏没有展开,您将无法获得任何有用的信息,因为宏展开成的内容对您来说是完全不透明的。也许有人写过这个函数:

(defn foo [x]
  (-> x
      inc
      println))

如果不展开-> 宏,您将不会发现foo 依赖于incprintln。并且发现它依赖于-> 并不是很有趣。

【讨论】:

  • 当然,但如果-> 已由用户定义——目前,扩展会导致它“消失”——至少据我所知。我在 ast 中找不到 var。但问题是我无法从 ast 中分辨出什么是宏。我想我想做的是扩展,以便我可以捕获参数并测试它们 - 但忽略所有进入 '->' 的杂物。我不在乎-> 是如何定义的,我只想知道它来自哪里(是的,它需要的参数)
  • 你明白我在问题中给出的例子的意思吗 - 你能看到没有引用 log/info 即使这是被调用的宏。
  • 在您的示例中,(macroexpand '(-> 10 (partial + 1))) 变为 (partial 10 + 1)-> 至关重要,因为如果重新编写,结果会发生变化。我想我只是要编写自己的解析器......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-17
  • 1970-01-01
相关资源
最近更新 更多