我已经搜索了"clojure dynamic"和"clojure dynamic scope"并阅读了10篇文章,我仍然没有清楚地了解它的^:dyanmic作用. 我认为这篇文章可能正在回答我的问题,但代码示例似乎"缺失",所以我甚至不确定它是否指的是我对此感到困惑的相同内容.
我正在尝试解决clj-http项目中的问题,但首先我必须了解代码.它具有如下定义的函数:
(defn ^:dynamic parse-html
"Resolve and apply crouton's HTML parsing."
[& args]
{:pre [crouton-enabled?]}
(apply (ns-resolve (symbol "crouton.html") (symbol "parse")) args))
Run Code Online (Sandbox Code Playgroud)
但我不明白这^:dynamic意味着什么.有人能以一种非常简单的方式向我解释吗?
它将函数定义为动态范围.
换句话说,这允许某人parse-html在给定的函数调用中重新绑定,并使该新绑定仅应用于从该特定调用调用的函数.
如果parse-html没有动态范围,那么重新绑定它将导致新绑定被任何使用的代码看到parse-html,而不仅仅是由执行重新绑定的函数调用激活的代码.
动态范围可用作全局范围变量的替代.一个函数可以说"let current_numeric_base = 16;调用其他函数"; 其他功能都将以十六进制打印.然后当它们返回并且基本设置函数返回时,基数将返回到它的任何位置. http://c2.com/cgi/wiki?DynamicScoping
正如下面的评论中指出的那样,您实际上无法重新绑定在Clojure中没有动态作用域的变量.如果可以,更新词法范围的变量将影响所有执行的代码,即使它在重新绑定发生的不同调用堆栈中运行.
因此,一些伪代码可能会使动态范围和词汇范围之间的区别变得清晰.
使用动态范围变量的示例:
(def ^:dynamic a 0)
(defn some-func [x] (+ x 1))
; re-binds a to 1 for everything in the callstack from the (binding)
; call and down
(binding [a 1]
(print (some-func a)))
; a was only re-bound for anything that was called from
; within binding (above) so at this point a is bound to 0.
(print (some-func a))
Run Code Online (Sandbox Code Playgroud)
会打印: 2 1
词法范围变量的示例:
(def a 0)
(defn some-func [x] (+ x 1))
; re-binds a to 1 for everyone, not just things that
; are in the callstack created at this line
(set-var [a 1] ; set-var is a made up function that can re-bind lexically scoped variables
(print (some-func a)))
; a was lexically scoped so changing it changed
; it globally and not just for the callstack that
; contained the set-var.
(print (some-func a))
Run Code Online (Sandbox Code Playgroud)
会打印: 2 2