使用var quote语法调用Clojure函数
偶尔在查看其他人的Clojure代码时,我会看到通过使用var quote语法调用Clojure函数,clojure,eval,var,Clojure,Eval,Var,偶尔在查看其他人的Clojure代码时,我会看到通过defn定义的函数,然后使用var quote语法调用,例如: user> (defn a [] 1) #'user/a user> (a) ; This is how you normally call a function 1 user> (#'a) ; This uses the var-quote syntax and produces the same result 1 就我个人而言,我无法理解这两种调用函数的
defn
定义的函数,然后使用var quote语法调用,例如:
user> (defn a [] 1)
#'user/a
user> (a) ; This is how you normally call a function
1
user> (#'a) ; This uses the var-quote syntax and produces the same result
1
就我个人而言,我无法理解这两种调用函数的方式之间的区别。我在文档中找不到任何东西可以说明当调用的操作符是var时会发生什么,这可能表明为什么会首选第二种形式。它们对绑定
赋值和语法引用的响应似乎相同
那么,有人能提供一个代码示例来说明上面的(a)
和(#'a)
之间的区别吗
编辑:我知道var quote可以用来获取被let
词法绑定隐藏的var,但我看到的代码似乎不是这样。(#a)
总是指vara
,而(a)
可以被本地绑定隐藏:
user> (defn a [] 1)
#'user/a
user> (let [a (fn [] "booh")] [(a) (#'a)])
["booh" 1]
但是,var quote/函数调用的大多数实际用途不是直接调用var quote表达式,而是缓存其值,以便高阶构造在传入时引用var a的当前值,而不是其值:
(defn a [] 1)
(defn my-call [f] (fn [] (+ 1 (f))))
(def one (my-call a))
(def two (my-call #'a))
(defn a [] 2)
user> (one)
2
user> (two)
3
这对于交互式开发非常有用,在交互式开发中,您正在更改一些函数,这些函数被包装在其他包中的一组其他函数中 第二种形式允许您绕过clojure设置的隐私限制 因此,例如,如果您开发了一个带有私有函数的库,但希望从一个单独的名称空间测试它们,那么您不能直接引用它们。但是您可以使用var quote语法访问它们。这是非常有用的 隐私是clojure本质上是一种自动文档,与Java中的隐私不同。你可以绕过它
user> (defn- a [] 1)
#'user/a
user> (ns user2)
nil
user2> (user/a)
CompilerException java.lang.IllegalStateException: var: #'user/a is not public, compiling:(NO_SOURCE_PATH:1)
user2> (#'user/a)
1
user2>
很好的一点——既然你提到了这一点,我记得过去我自己也做过。但是我看到的代码是调用非私有fn,所以我认为避免缓存当前绑定的值是更可能的解释,因为代码在私有回购中。我发布了一个一般性问题,得到了两个好答案,只能接受一个,所以我接受了一个我觉得更好的问题,回答了一般情况。