1

我正在尝试编写一个宏,给定一个表单,将所有缺少的符号定义为它们自己。

到目前为止,我有以下内容:

(def ^:private missing-symbol-pattern #"Unable to resolve symbol: (.+) in this context")

(cl/defn ^:private missing-symbol [s]
  (cl/when-let [[_ sym] (cl/re-find missing-symbol-pattern s)] sym))

(cl/defmacro try-eval [expr]
               `(try (do (cl/println '~expr) (cl/eval '~expr)) 
                 (catch Exception e#
                   (cl/if-let [sym# (do (cl/println (.getMessage e#)) (missing-symbol (.getMessage e#)))]
                              (cl/eval `(do 
                                          (def ~(cl/symbol sym#) '~(cl/symbol sym#))
                                          (cl/println ~sym#)
                                          (try-eval ~'~expr)))
                              (cl/eval `(throw ~e#))))))

cl这里是 的别名clojure.core)我知道副作用可能会出现问题,但这在这里并不重要(尽管没有副作用问题的解决方案会更好)

如果有多个丢失(无法解析)的符号,我会收到以下异常:

java.lang.RuntimeException: Can't embed object in code, maybe print-dup not defined: java.lang.ClassCastException: clojure.lang.Symbol cannot be cast to clojure.lang.IDeref, compiling:(shen/primitives.clj:517)

有人知道要改变什么吗?有一些“现成的”解决方案吗?

干杯

4

1 回答 1

3

&env与其使用 try/catch 来查找无法解析的符号,不如使用defmacro. 的键&env是本地定义的符号。

关于 &env 和 &form 的文章。

使用 和 的组合可以隔离未定义的符号,resolve然后(keys &env)您可以选择定义未定义的符号(not (or (resolve sym) (contains? &env sym))

我们在Midje 源代码中做了类似的事情,以确定表格测试中的哪些符号已定义,哪些未定义:

[注:在下面的代码locals实际上是(keys &env)]

(defn- headings-rows+values [table locals]
  (letfn [(table-variable? [s]
            (and (symbol? s)
              (not (metaconstant-symbol? s))
              (not (resolve s))
              (not (contains? locals s))))]
    (split-with table-variable? (remove-pipes+where table))))
于 2012-04-21T18:02:33.877 回答