gpt4 book ai didi

clojure - 如何找到 Clojure 表达式中的所有自由变量?

转载 作者:行者123 更新时间:2023-12-04 18:01:22 25 4
gpt4 key购买 nike

如何找到 Clojure 表达式中的所有自由变量?

作者 自由变量 , 我的意思是所有没有定义在本地环境中的符号(包括所有定义在表达式内部的局部环境),没有定义在全局环境中(所有在当前命名空间中的符号,包括所有从其他命名空间导入的符号),而不是Clojure 原语。

例如,这个表达式中有一个自由变量:

(fn [ub]
(* (rand-int ub) scaling-factor))

那就是 scaling-factor . fn , * , 和 rand-int都是在全局环境中定义的。 ub是在它发生的范围内定义的,所以它也是一个绑定(bind)变量(即不是自由的)。

我想我可以自己写这个——看起来并不难——但我希望有一些我应该使用的标准方法,或者访问 Clojure 编译器的标准方法(因为 Clojure编译器当然也必须这样做)。简单实现的一个潜在缺陷是表达式中的所有宏都必须完全扩展,因为宏可以引入新的自由变量。

最佳答案

您可以使用 tools.analyzer.jvm 分析表单传递特定的回调来处理无法解析的符号。
像这样的东西:

(require '[clojure.tools.analyzer.jvm :as ana.jvm])

(def free-variables (atom #{}))

(defn save-and-replace-with-nil [_ s _]
(swap! free-variables conj s)

;; replacing unresolved symbol with `nil`
;; in order to keep AST valid
{:op :const
:env {}
:type :nil
:literal? true
:val nil
:form nil
:top-level true
:o-tag nil
:tag nil})

(ana.jvm/analyze
'(fn [ub]
(* (rand-int ub) scaling-factor))
(ana.jvm/empty-env)
{:passes-opts
(assoc ana.jvm/default-passes-opts
:validate/unresolvable-symbol-handler save-and-replace-with-nil)})

(println @free-variables) ;; => #{scaling-factor}

它还将正确处理宏扩展:
(defmacro produce-free-var []
`(do unresolved))

(ana.jvm/analyze
'(let [x :foo] (produce-free-var))
(ana.jvm/empty-env)
{:passes-opts
(assoc ana.jvm/default-passes-opts
:validate/unresolvable-symbol-handler save-and-replace-with-nil)})

(println @free-variables) ;; => #{scaling-factor unresolved}

关于clojure - 如何找到 Clojure 表达式中的所有自由变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48533064/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com