未互连符号 [英] Uninterned symbols symbols

查看:107
本文介绍了未互连符号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于普通的Lisp,我有些不了解。

There is something I can't understand about Common lisp.

假设我正在编写类似于以下内容的宏:

Assume I'm writing a macro similar to this:

(defmacro test-macro () 
   (let ((result (gensym))) 
      `(let ((,result 1))
         (print (incf ,result))))) 

我能做的

> (test-macro)
2
2

现在我想看看

> (macroexpand-1 '(test-macro))
(LET ((#:G4315 1)) (PRINT (INCF #:G4315))) ;
T

好。

据我所知,未生成的符号是评估者不会为其创建符号的符号,内部数据绑定。

So as far as I know the uninterned symbols are the symbols for which the evaluator does't create symbol-data binding internally.

因此,如果我们将宏宏扩展为该形式,则应该出现错误(incf#:G4315)。
要测试这一点,我们可以在REPL中评估该表格:

So, if we macro-expand to that form there should be an error on (incf #:G4315). To test this we can just evaluate that form in the REPL:

> (LET ((#:G4315 1)) (PRINT (INCF #:G4315)))
*** - SETQ: variable #:G4315 has no value

那么为什么扩展到该字符串的宏可以完美地工作而表单本身却不能呢?

So why does the macro that expands to this string works perfectly and the form itself does not?

推荐答案

可以在一个程序包中插入或不插入符号。可以查找并找到在程序包中插入的符号。无法在包装中查找未识别的符号。程序包中只能有一个名称相同的符号。只有一个符号 CL-USER :: FRED

Symbols can be interned in a package or not. A symbol interned in a package can be looked up and found. An uninterned symbol can't be looked up in a package. Only one symbol of a certain name can be in a package. There is only one symbol CL-USER::FRED.

您写


到目前为止据我所知,未中断符号是评估者未在内部创建符号数据绑定的符号。

So as far as I know the uninterned symbols are the symbols for which the evaluator does't create symbol-data binding internally.

这是错误的。未互连符号是​​指在任何程序包中都不 interned 的符号。否则,它们会很好。 interned 表示在软件包的注册表中为其符号注册的

That's wrong. Uninterned symbols are symbols which are not interned in any package. Otherwise they are perfectly fine. interned means registered in the package's registry for its symbols.

s- reader 表达式确实使用符号名称和程序包在 reading 期间识别符号。如果没有这样的符号,则将其屏蔽。如果有一个,则返回这个。

The s-expression reader does use the symbol name and the package to identify symbols during reading. If there is no such symbol, it is interned. If there is one, then this one is returned.

阅读器确实按符号名称查找符号,在当前程序包中位于此处:

The reader does look up symbols by their name, here in the current package:

 (read-from-string "FOO") -> symbol `FOO`

第二次:

 (read-from-string "FOO") -> symbol `FOO`

它始终是同一符号 FOO

 (eq (read-from-string "FOO") (read-from-string "FOO"))  -> T

#:FOO 是一个名称为 FOO 的未绑定符号。它没有在任何程序包中实习。如果读者看到此语法,它将创建一个新的未隔离符号。

#:FOO is the syntax for an uninterned symbol with the name FOO. It is not interned in any package. If the reader sees this syntax, it creates a new uninterned symbol.

 (read-from-string "#:FOO") -> new symbol `FOO`

第二次:

 (read-from-string "#:FOO") -> new symbol `FOO`

两个符号都不同。它们具有相同的名称,但是它们是不同的数据对象。除了软件包外,没有其他用于符号的注册表。

Both symbols are different. They have the same name, but they are different data objects. There is no other registry for symbols, than the packages.

 (eq (read-from-string "#:FOO") (read-from-string "#:FOO"))  -> NIL

因此在您的情况下(LET((#:G4315 1)) (PRINT(INCF#:G4315)),未插入的符号是不同的对象。那么第二个变量是一个不同的变量。

Thus in your case (LET ((#:G4315 1)) (PRINT (INCF #:G4315))), the uninterned symbols are different objects. The second one then is a different variable.

Common Lisp可以打印数据,以便在打印/读取过程中保留身份

CL-USER 59 > (macroexpand-1 '(test-macro))
(LET ((#:G1996 1)) (PRINT (INCF #:G1996)))
T

CL-USER 60 > (setf *print-circle* t)
T

CL-USER 61 > (macroexpand-1 '(test-macro))
(LET ((#1=#:G1998 1)) (PRINT (INCF #1#)))
T

现在您看到打印的s表达式带有标签#1 = 为第一个符号。然后,它稍后引用相同的变量。可以回读并保留符号身份-即使 reader 不能通过查看包来识别符号。

Now you see that the printed s-expression has a label #1= for the first symbol. It then later references the same variable. This can be read back and the symbol identities are preserved - even though the reader can't identify the symbol by looking at the package.

因此,宏创建了一种形式,其中仅生成一个符号。当我们打印该表格并想读回时,我们需要确保保留未中断符号的身份。将 * print-circle * 设置为 T 进行打印有助于实现此目的。

Thus the macro creates a form, where there is only one symbol generated. When we print that form and want to read it back, we need to make sure that the identity of uninterned symbols is preserved. Printing with *print-circle* set to T helps to do that.

问:为什么我们通过使用 GENSYM 生成符号)在宏中使用未生成的生成符号?

Q: Why do we use uninterned generated symbols in macros by using GENSYM (generate symbol)?

这样,我们可以拥有不与代码中其他符号冲突的独特新符号。他们通过函数 gensym 来获得名称-通常在末尾加上一个已计数的数字。由于它们是没有包装在任何包装中的新的新符号,因此不会存在任何命名冲突。

That way we can have unique new symbols which do not clash with other symbols in the code. They get a name by the function gensym- usually with a counted number at the end. Since they are fresh new symbols not interned in any package, there can't be any naming conflict.

CL-USER 66 > (gensym)
#:G1999

CL-USER 67 > (gensym)
#:G2000

CL-USER 68 > (gensym "VAR")
#:VAR2001

CL-USER 69 > (gensym "PERSON")
#:PERSON2002

CL-USER 70 > (gensym)
#:G2003

CL-USER 71 > (describe *)

#:G2003 is a SYMBOL
NAME          "G2003"
VALUE         #<unbound value>
FUNCTION      #<unbound function>
PLIST         NIL
PACKAGE       NIL                      <------- no package

这篇关于未互连符号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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