gpt4 book ai didi

clojure - Clojure 中符号和变量的区别

转载 作者:行者123 更新时间:2023-12-02 00:48:10 25 4
gpt4 key购买 nike

我总是对 Clojure 中的符号和变量有点困惑。例如,可以肯定地说+是一个符号,用于表示一个var,而这个var指向一个值,该值是一个可以与数字相加的函数?

那么当我在 REPL 中输入“+”时,一步一步会发生什么?

  1. 符号获得命名空间的资格,在本例中为 clojure.core
  2. 然后在某个符号表中有+引用var的信息
  3. 当这个变量被求值时,结果是一个函数值?

最佳答案

有一个符号+,你可以通过引用它来谈论它:

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>

请注意,词法绑定(bind)是一种不同的机制,它们可以隐藏 Var,但您可以通过显式引用 Var 来绕过它们:

user=> (let [+ -] [(+ 1 2) (@#'+ 1 2)])
[-1 3]

在最后一个示例中,甚至可以省略 deref:

user=> (let [+ -] [(+ 1 2) (#'+ 1 2)])
[-1 3]

这是因为 Var 通过调用 deref 自身、将结果转换为 IFn 并将函数调用委托(delegate)给它来实现 IFn(Clojure 函数的接口(interface))。

使用 defn- 定义私有(private)函数时使用的可见性机制基于符号的元数据。您可以通过直接引用 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

关于clojure - Clojure 中符号和变量的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9113387/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com