我想执行一些依赖于某个var的Clojure代码,但只有在定义了var 时才执行。作为简化示例,只有在定义if
时才能执行sym
表单的正文:
(if (resolve 'sym) (println sym))
不幸的是,这不起作用。如果未定义sym
,编译器仍会尝试解析它并抛出:
CompilerException java.lang.RuntimeException: Unable to resolve symbol: sym in this context
通过阅读Rich Hickley的评论here,我发现这种行为是由于Clojure使用(主要是)单通道编译。然而,尽管有这么多意义,但在这种情况下显然会导致不良行为。
我可以通过在运行时强制执行符号解析来解决问题:
(if (resolve 'sym) (println (deref (resolve 'sym))))
但这是一个不受欢迎的黑客行为。有没有更好的方法,或者Clojure的read-eval模型是不可能的?
(为什么我需要这样做?我在profiles.clj
中定义了多个可组合的配置文件。其中一个用于vinyasa,这使我能够方便地注入各种功能可访问的.
名称空间。其他人加载各种其他实用程序库。在其他实用程序库的配置文件中,我想使用vinyasa注入最重要的函数,但仅在加载vinyasa时。我currently using是上述黑客的变种。)
答案 0 :(得分:1)
(defn get-when-var-defined [sym]
(when-let [var-for-sym (resolve sym)]
@var-for-sym))
(get-when-var-defined 'foo) ;;=> nil
(def foo 1)
(get-when-var-defined 'foo) ;;=> 1
答案 1 :(得分:1)