Clojure 中的符号 [英] Symbols in Clojure

查看:13
本文介绍了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.

从 Lisp 的一般性到 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 绑定/名称为 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这样的符号,当在命名空间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,它 refer s 到 clojure.zip 而没有use'ing it) 将在适当的命名空间中查找.

A symbol which is already namespace-qualified (something like a zip/root in a namespace which refers to clojure.zip without use'ing it) will be looked up in the appropriate namespace.

宏会增加一些复杂性(它只能出现在操作符位置),但这与符号本身的行为并不真正相关.

There's some added complexity with macros (which can only occur in operator position), but it's not really something relevant to the behaviour of symbols themselves.

请注意,在 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 在评估符号时会继续寻找其他对象.符号本身没有用于绑定对象的槽"或字段";任何将符号绑定"到某个对象的印象都是由于 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

最后一个解释:'s(quote s)的简写;这是一个列表结构,而不是一个符号.宏对其直接传入的参数进行操作,无需求值;所以在 (symbol??'s) 中,它实际上看到了 (quote s) 列表结构,它本身当然不是一个符号——尽管当传递给 eval,它将评估为 1.

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屋!

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