gpt4 book ai didi

clojure - Clojure 中的符号

转载 作者:行者123 更新时间:2023-12-03 09:00:36 24 4
gpt4 key购买 nike

Clojure 中的 Symbols 绑定(bind)到底层对象并具有可选的单独值的基本原理是什么?也许我缺少一些基本的东西,但如果有人能指出为什么会很棒。

最佳答案

一般介绍:

任何 Lisp 中的符号都用作标识符。如果你要引用一个变量的值,比如说,你需要有一种命名它的方法;这就是符号的用途。请记住,所有 Lisp 代码在读取时都会被转换为 Lisp 数据结构;标识符也必须由某种数据结构表示,它恰好是符号。遇到符号时,eval调度到某种“名称查找”操作。

从 Lisp 通用性转移到 Clojure 细节,Clojure eval/编译器的行为是,在遇到符号时,它会将其作为 let 的名称。 - 引入局部变量或函数参数或命名空间中的条目名称。实际上,只有非命名空间限定的符号可以用于第一个容量(意味着 foo 形式的符号而不是 some-namespace/foo )。

一个粗略的例子:

对于非命名空间限定符号 foo , 如果一个 let名称的绑定(bind)/函数参数foo找到时,符号计算为其值。如果不是,则符号将转换为 *ns*/foo 形式(*ns* 表示当前命名空间)并尝试在 *ns* 中查找相应条目;如果有这样的条目,则返回其值,如果没有,则抛出异常。

请注意,像 identity 这样的符号, 在命名空间 quux 中使用时, 将解析为 clojure.core/identity通过一个中间步骤,其中 quux/identity 下的条目被发现;这通常是指 clojure.core/identity .这是一个在直观编码时不会想到的实现细节,但在试图解释这一点时我发现不可能不提。

一个已经被命名空间限定的符号(类似于 zip/root 的命名空间中的 referclojure.zip 而没有 use 的符号)将在适当的命名空间中查找。

宏增加了一些复杂性(只能出现在运算符位置),但这与符号本身的行为并不真正相关。

变量与符号:

请注意 在 Clojure 中,符号本身并不是存储位置 -- 变量是。因此,当我在上面说在命名空间中查找符号时,我的意思是 eval查找由解析为其命名空间限定形式的符号命名的 Var,然后取其值。特殊表格var (通常缩写为 #' )修改此行为以便返回 Var 对象本身。不过,符号到变量解析的机制没有改变。

结束语:

请注意,所有这一切都意味着符号仅“绑定(bind)”到对象上,eval ,在评估一个符号时,继续寻找一些进一步的对象。符号本身没有用于绑定(bind)对象的“槽”或“域”;符号“绑定(bind)”到某个对象的任何印象都是由于 eval的工作。这是 Clojure 的一个特性,因为在一些 Lisps 中,符号本身就充当了存储位置。

最后,可以使用通常的引用机制来防止对符号进行求值:在 'foo 中, 符号 foo不会被评估(因此不会执行任何类型的名称查找);它将原封不动地返回。

回应 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 时,它将评估为一。

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

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