Clojure中的符号 [英] Symbols in Clojure

查看:98
本文介绍了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 refers 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屋!

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