有一个符号+,你可以通过引用它来谈论它:
user=> '+
+
user=> (class '+)
clojure.lang.Symbol
user=> (resolve '+)
#'clojure.core/+
所以它解析为#'+,这是一个Var:
user=> (class #'+)
clojure.lang.Var
Var 引用函数对象:
user=> (deref #'+)
#<core$_PLUS_ clojure.core$_PLUS_@55a7b0bf>
user=> @#'+
#<core$_PLUS_ clojure.core$_PLUS_@55a7b0bf>
(@ 符号只是 deref 的简写。)当然,获取函数的常用方法是不引用符号:
user=> +
#<core$_PLUS_ clojure.core$_PLUS_@55a7b0bf>
请注意,词法绑定是一种不同的机制,它们可以影响 Var,但您可以通过显式引用 Var 来绕过它们:
user=> (let [+ -] [(+ 1 2) (@#'+ 1 2)])
[-1 3]
在最后一个示例中,甚至可以省略 deref:
user=> (let [+ -] [(+ 1 2) (#'+ 1 2)])
[-1 3]
这是因为 Var 通过调用自身的 deref 来实现 IFn(Clojure 函数的接口),将结果转换为 IFn 并将函数调用委托给它。
使用 defn- 定义私有函数时使用的可见性机制基于符号上的元数据。你可以通过直接引用Var来绕过它,如上:
user=> (ns foo)
nil
foo=> (defn- private-function [] :secret)
#'foo/private-function
foo=> (in-ns 'user)
#<Namespace user>
user=> (foo/private-function)
java.lang.IllegalStateException: var: #'foo/private-function is not public (NO_SOURCE_FILE:36)
user=> (#'foo/private-function)
:secret