Clojure 中符号和变量的区别 [英] Difference between Symbols and Vars in Clojure

查看:20
本文介绍了Clojure 中符号和变量的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我总是对 Clojure 中的 Symbols 和 Vars 有点困惑.例如,是否可以说 + 是一个用于表示 var 的符号,而这个 var 指向一个值,该值是一个可以加法的函数?

I'm always a bit confused about Symbols and Vars in Clojure. For example, is it safe to say that + is a symbol which is used to denote a var, and this var points to a value which is a function that can add numbers?

当我在 REPL 中输入+"时,会发生什么?

So what happens, step by step when I just enter "+" in a REPL?

  1. 符号被限定为命名空间,在本例中为 clojure.core
  2. 然后在一些符号表中有 + 指代 var 的信息
  3. 当这个 var 被求值时,结果是一个函数值?

推荐答案

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

There's a symbol + that you can talk about by quoting it:

user=> '+
+
user=> (class '+)
clojure.lang.Symbol
user=> (resolve '+)
#'clojure.core/+

所以它解析为#'+,这是一个Var:

So it resolves to #'+, which is a Var:

user=> (class #'+)
clojure.lang.Var

Var 引用函数对象:

The Var references the function object:

user=> (deref #'+)
#<core$_PLUS_ clojure.core$_PLUS_@55a7b0bf>
user=> @#'+
#<core$_PLUS_ clojure.core$_PLUS_@55a7b0bf>

(@ 符号只是 deref 的简写.)当然,获取函数的常用方法是不引用符号:

(The @ sign is just shorthand for deref.) Of course the usual way to get to the function is to not quote the symbol:

user=> +
#<core$_PLUS_ clojure.core$_PLUS_@55a7b0bf>

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

Note that lexical bindings are a different mechanism, and they can shadow Vars, but you can bypass them by referring to the Var explicitly:

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

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

In that last example the deref can even be left out:

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

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

This is because Var implements IFn (the interface for Clojure functions) by calling deref on itself, casting the result to IFn and delegating the function call to that.

使用 defn- 定义私有函数时使用的可见性机制基于符号的元数据.您可以通过直接引用 Var 来绕过它,如上所示:

The visibility mechanism used when you define private functions with defn- is based on metadata on the symbol. You can bypass it by referring directly to the Var, as above:

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 中符号和变量的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆