我在REPL中发生了以下情况:
mathematics.core> (let [zebra 1] (resolve 'zebra))
nil
mathematics.core> (def zebra 1)
#'mathematics.core/zebra
mathematics.core> (let [zebra 2] (when (resolve 'zebra) (eval 'zebra)))
1基本上,我希望使用类似于let表单的东西将值动态绑定到变量,并使该表单中的函数能够访问变量绑定到的值。
mathematics.core> (def ^:dynamic zebra 1)
#'mathematics.core/zebra
mathematics.core> (binding [zebra 2] (when (resolve 'zebra) (eval 'zebra)))
2binding似乎做了我想要的把戏,但是AFAIK它首先需要用:dynamic元数据定义一个变量。我希望能够动态地使用以前从未定义过的变量,并让形式中的表达式能够访问该变量,就像它是实际定义的一样。
为了说明,我想要这样的东西:
mathematics.core> (let-dynamic [undefined-variable 1]
(when (resolve 'undefined-variable) (eval 'unresolved-variable)))
1有什么简单的方法可以做到这一点吗?或者是一种使用宏来完成此任务的方法?
发布于 2012-01-20 18:43:17
这不会很好地工作。如果没有定义这个符号,那么Clojure编译器就不能编译任何使用它的代码。你也许能够在需要的时候使用一些延迟调用def的宏,但这将是一些非常糟糕的代码.
我建议只使用绑定,并提前定义您的var。你应该能够以这种方式编写你的代码。
我认为“即时”定义变量不是一个好主意。我认为你不应该真的需要这个--如果你在代码中使用变量,那么只需预先为你使用的每个变量做一个(def ^:dynamic ...)就足够简单了。
发布于 2012-01-20 17:38:49
我希望能够动态地使用以前从未定义过的变量,并让形式的表达式能够访问该变量,就像它是实际定义的一样。
在我看来,这对于clojure的vars或let-bound值来说并不是一个很好的匹配,如果您无论如何都是在动态生成和求值整个表单,为什么不使用一个简单的映射来存储符号->值映射,并用映射查找替换整个解析/求值方案?这样,您就可以动态生成任意符号,而不会出现任何晦涩难懂的名称空间技巧,这些技巧可能会以难以找到的方式破坏您的代码:
(let [my-resolve {'zebra 1}]
(println "zebra is " (my-resolve 'zebra)))发布于 2012-01-20 19:18:57
虽然这不是一个完整的解决方案,但这里是一个尝试:
(defmacro let-dynamic
([[sym val & more] & body]
`(do (when (not (:dynamic (meta (resolve '~sym))))
(def ~(with-meta sym {:dynamic true}) ~sym))
(binding [~sym ~val]
~@(if (empty? more)
body
`((let-dynamic ~more ~@body)))))))一个小测试:
blub> (def ^:dynamic already-dynamic 'dynamic)
#'blub/already-dynamic
blub> (def not-dynamic 'not-dynamic)
#'blub/not-dynamic
blub> (let-dynamic [already-dynamic 2] already-dynamic)
2
blub> (let-dynamic [not-dynamic 2] not-dynamic)
2
blub> (let-dynamic [not-dynamic-and-not-defined 2] not-dynamic-and-not-defined)
2
blub> 这有几个问题:
由于某种原因,将多个符号-值对传递给-
https://stackoverflow.com/questions/8938398
复制相似问题