Clojure中的符号 [英] Symbols in Clojure
问题描述
Clojure中的符号绑定到底层对象并有可选的单独值的原因是什么?
What is the rationale for Symbols in Clojure to be bound to an underlying object and have an optional separate value ? Perhaps something elementary I am missing but would be great if someone could point out the Why.
推荐答案
一般介绍:
如果有人可以指出为什么,任何Lisp中的符号都用作标识符。如果你要引用一个变量的值,比如说,你需要有一个命名方法;这就是符号是什么。请记住,所有Lisp代码在读取时都会转换为Lisp数据结构;标识符也必须由一些数据结构表示,它恰好是符号。遇到符号时, eval
会调度到某种名称查找操作。
General intro:
Symbols in any Lisp are used as identifiers. If you're going to refer to the value of a variable, say, you need to have a way of naming it; that's what symbols are for. Remember that all Lisp code gets translated at read time to Lisp data structures; identifiers must also be represented by some data structure and it happens to be the symbol. Upon encountering a symbol, eval
dispatches to some kind of a "name lookup" operation.
到Clojure的细节,Clojure的eval /编译器的行为是遇到一个符号,它将它作为一个名称为 let
引入的局部变量或函数参数或命名空间中的条目的名称。实际上只有非命名空间限定的符号可以在第一个容量中使用(意味着符号 foo
而不是 some-namespace / foo
)。
Moving from Lisp generalities to Clojure particulars, the behaviour of the Clojure eval / compiler is that upon encountering a symbol, it takes it to be a name for either a let
-introduced local variable or function parameter or the name of an entry in a namespace. Actually only non-namespace-qualified symbols may be used in the first capacity (meaning symbols of the form foo
and not some-namespace/foo
).
对于非命名空间限定的符号 foo
,如果 let
绑定/函数参数name foo
,则符号求值为其值。如果不是,则符号变换为 * ns * / foo
( * ns *
表示当前命名空间)并尝试在 * ns *
中查找对应的条目;
For a non-namespace-qualified symbol foo
, if a let
binding / function parameter of name foo
is found, the symbol evaluates to its value. If not, the symbol gets transformed to the form *ns*/foo
(*ns*
denotes the current namespace) and an attempt is made to look up a curresponding entry in *ns*
; if there is such an entry, its value is returned, if not, an exception is thrown.
请注意,像 identity $>这样的符号会产生异常。 c $ c>在命名空间
quux
中使用时,将通过中间步骤解析为 clojure.core / identity
其中发现 quux / identity
下的条目;这通常会指向 clojure.core / identity
。这是一个实现细节,一个人不会想到当编码直观,但我觉得不可能不提到当试图解释这一点。
Note that a symbol like identity
, when used in namespace quux
, will be resolved to clojure.core/identity
through an intermediate step in which an entry under quux/identity
is discovered; this will normally refer to clojure.core/identity
. That's an implementation detail one doesn't think of when coding intuitively, but which I find impossible not to mention when trying to explain this.
一个符号已经是命名空间 - 合格的(指向
的名称空间中的
zip / root
)clojure.zip
A symbol which is already namespace-qualified (something like a zip/root
in a namespace which refer
s to clojure.zip
without use
'ing it) will be looked up in the appropriate namespace.
请注意,在Clojure中,符号本身不是存储位置 - 变量。所以当我在上面说一个符号在命名空间中查找时,我的意思是 eval
查找由符号命名的Var解析为其命名空间限定形式,然后取值的。特殊形式 var
(通常缩写为#'
)修改此行为,以便返回Var对象本身。
Note that in Clojure, symbols are not themselves storage locations -- Vars are. So when I say in the above that a symbol gets looked up in a namespace, what I mean is that eval
looks up the Var named by the symbol resolved to its namespace-qualified form and then takes the value of that. The special form var
(often abbreviated to #'
) modifies this behaviour so that the Var object itself is returned. The mechanics of symbol-to-Var resolution are unchanged, though.
请注意,所有这意味着符号只是绑定对象的意义上的 eval
,当评估一个符号,继续寻找一些进一步的对象。符号本身没有要绑定到它的对象的slot或field;任何符号被绑定到某个对象的印象是由于 eval
的工作原理。这是一个Clojure特性,因为在一些Lisps符号本身作为存储位置。
Note that all this means that symbols are only "bound" to objects in the sense that eval
, when evaluating a symbol, goes on to look for some further object. The symbol itself has no "slot" or "field" for an object to be bound to it; any impression that a symbol is "bound" to some object is due to eval
's workings. This is a Clojure characteristic, as in some Lisps symbols do themselves act as storage locations.
最后,可以使用通常的引用机制来防止符号的评估:在'foo
,符号 foo
不会被评估(因此不会执行任何类别的名称查找);
Finally, one can use the usual quoting mechanism to prevent the evaluation of a symbol: in 'foo
, the symbol foo
will not be evaluted (so no name lookup of any sort will be performed); it'll be returned unchanged instead.
回应OP的评论:试试这个有趣的:
(defmacro symbol?? [x]
(if (symbol? x)
true
false))
(def s 1)
(symbol? s)
; => false
(symbol?? s)
; => true
(symbol? 's)
; => true
(symbol?? 's)
; => false
最后一个解释:'
是(quote s)
的缩写;这是一个列表结构,而不是一个符号。宏操作其直接传递的参数,而不进行评估;所以在(符号??的)
它实际上看到(quote s)
列表结构,本身并不是一个符号 - 虽然传递给 eval
,它将计算为一个。
The last one explained: 's
is shorthand for (quote s)
; this is a list structure, not a symbol. A macro operates on its arguments passed in directly, without being evaluated; so in (symbol?? 's)
it actually sees the (quote s)
list structure, which is of course not itself a symbol -- although when passed to eval
, it would evaluate to one.
这篇关于Clojure中的符号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!