我是否遗漏了一些关于在 LISP 中驻留符号的重要事实?
长话短说。这是我在 clisp 中实习和使用符号的几次尝试。
[1]> (setq sym (intern "foo"))
|foo|
[2]> (eq sym 'foo)
NIL
为什么???
[3]> (defun internup (me &optional (package *package*))
(intern (string-upcase me) package))
INTERNUP
[4]> (eq 'abc (internup "abc"))
T
可能必须是大写。
[12]>(let ((abc 2))
(eval '(+ 2 abc)))
*** - EVAL: variable ABC has no value
The following restarts are available:
好吧,
[18]> (let ((abc 2))
(eval '(+ 2 'abc)))
*** - +: ABC is not a number
The following restarts are available:
有趣。我应该先设置一下吗?
[14]> (setq a (internup "abc"))
ABC
[15]> (let ((abc 2))
(eval '(+ 2 a)))
*** - +: ABC is not a number
The following restarts are available:
又错了。嗯,我一定错过了一些关于在 LISP 中驻留符号的重要事实。你能帮助我吗 ?
To be brief. Here is my several tries to intern and use a symbol in clisp.
[1]> (setq sym (intern "foo"))
|foo|
[2]> (eq sym 'foo)
NIL
Why???
[3]> (defun internup (me &optional (package *package*))
(intern (string-upcase me) package))
INTERNUP
[4]> (eq 'abc (internup "abc"))
T
Probably must be upcase.
[12]>(let ((abc 2))
(eval '(+ 2 abc)))
*** - EVAL: variable ABC has no value
The following restarts are available:
ok
[18]> (let ((abc 2))
(eval '(+ 2 'abc)))
*** - +: ABC is not a number
The following restarts are available:
Interesting. Should I set it before.
[14]> (setq a (internup "abc"))
ABC
[15]> (let ((abc 2))
(eval '(+ 2 a)))
*** - +: ABC is not a number
The following restarts are available:
And again wrong. Hmm I must be missing some important fact about interning symbols in LISP. Can you help me ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
你的问题与实习无关。
第一个问题确实是由于读者总是将符号大写而引起的,因此您需要调用 (intern "FOO") 才能获得与 'foo.
EVAL 的问题是由于 LET 引入了在 EVAL 内部不可见的词法绑定。如果你真的希望它起作用,你必须将 abc 声明为特殊的,如下所示:
特殊声明将导致变量具有动态绑定,而不是词法绑定(后者意味着绑定仅限于本地词法)上下文,即在 LET 形式中,通过特殊声明,该变量可用于从该形式调用的任何内容)。
请注意,特殊声明和 eval 的使用应该非常小心,并且您应该首先重新考虑 EVAL 的使用。您真正需要使用它的情况很少见。在大多数情况下,您实际上正在寻找 lambda 函数的使用。
Your problem has nothing to do with interning.
The first problem is indeed causes by the fact that the reader will always uppercase the symbols, so you need to call (intern "FOO") in order to get the same result as 'foo.
The problem with EVAL is caused by the fact that LET introduces a lexical binding which is not visible inside EVAL. If you really want this to work you'd have to declare abc to be special, like so:
A special declaration will cause the variable to have dynamic binding, instead of lexical binding (the latter means that the binding is limited to the local lexical context, i.e. within the LET form. With the special declaration the variable is available to anything that is called by from that form).
Note that the use of both special declarations and eval is something you should be very careful about and you should probably rethink your use of EVAL in the first place. It is very rare that you actually need to use it. In most cases you're actually looking for the use of lambda functions instead.
Eval
在空词法环境(即没有词法绑定)中计算形式。这与符号的驻留无关。Eval
evaluates the form in the null lexical environment, i.e. with no lexical bindings. That has nothing to do with the interning of symbols.Common Lisp 阅读器的大小写敏感度由可读表决定:
通常,阅读器最初会以大写形式存储符号(除非您明确转义字符)。因此:
(eq (intern "foo") 'foo)
=> NIL(eq (intern "FOO") 'foo)
=>; T(eq (intern "FOo") 'fo\o)
=>; 您可以使用反引号语法来构建 eval 的形式:
=> 4
The case-sensitivity of the Common Lisp reader is determined by the readtable:
Typically the reader will initially intern symbols in uppercase (unless you explicitly escape characters). Hence:
(eq (intern "foo") 'foo)
=> NIL(eq (intern "FOO") 'foo)
=> T(eq (intern "FOo") 'fo\o)
=> TYou can use backquote syntax to build the form for eval:
=> 4