deftype 如何处理符号以及为什么它与 defvar/defun 不同
How does deftype treat symbols and why does it differ from defvar/defun
Common Lisp 中符号的单元格绑定似乎没有扩展到 (deftype),是不是 (deftype) 将 [symbol, predicate body] 作为 [key, value] 添加到环境用于类型检查的关联映射中?
我明白为什么类型谓词不会存储在函数单元格中,但是没有 "special operator" 单元格或类型的专用 属性-list 属性是有原因的吗?说明符?
类型信息的存储位置完全取决于实现。某些实现可能会决定使用 symbol-plist。另一个可能会使用一些单独的 table,其中符号只是键。
我不会过多地了解这些细节。
CL 中的类型是 second-class 个对象:没有表示标准语言可用的类型的对象:只有 names of types – 类型说明符。所以很明显,类型没有访问器。此外,CL 中的类型通常根本不是用符号命名的:类型说明符可以是符号、classes 或各种列表。
第一个class 对象代表一些 类型:classes。 类 是 first-class CL中的对象,classes有一个访问器:find-class
。所以,例如
> (typep 1 'integer)
t
> (typep 1 (find-class 'integer))
但是 (find-class '(integer 0))
是一个错误,而 (typep 1 '(integer 0))
是好的(并且是真的)。
请注意,尽管 classes 不是类型:它们是类型 说明符(参见 4.2.3)并且仅适用于有限范围的类型。
符号是否具有 find-class
访问的特殊 'class' 插槽,或者 classes 是否存储在由符号索引的某些 table 中的其他地方,这取决于实现。从历史上看,后者显然是正确的,但至少现在某些实现可能有 class 个插槽。
实际上符号是否有任何槽完全取决于实现:symbol-value
、symbol-function
、symbol-plist
、symbol-package
, symbol-name
&c 可能引用某些 'symbol' 对象中的槽,或者它们可能只是引用由符号索引的 tables,其中符号只是 interned 字符串。当然,有些人会做一个,有些人会做另一个。
一个很好的例子是 symbol-value
:对于声明为特殊的变量 symbol-value
检索其当前动态值:
(let ((%x% 1))
(declare (special %x%))
(symbol-value '%x%))
计算为 1
。
但是有几种可能的方法可以实现这一点:在使用浅绑定的系统中,变量的绑定存储在与符号关联的某个槽中,并且这个槽会随着符号的变化而适当地修改绑定或未绑定,旧绑定存储在某个堆栈中(参见 Henry Baker's paper)。在具有深度绑定的系统中,它不是,绑定是通过搜索绑定堆栈来检索的。朴素的浅绑定系统在存在多线程时会出现相当严重的问题,而朴素的深度绑定系统则不会。使用哪种策略完全取决于实现,当然,这意味着它完全取决于实现 symbol-value
实际做什么以及符号是否有 'value' 个插槽。
我很确定所有使用多线程的实现都做了明显正确的事情:在像
这样的情况下
(let ((%x% 1))
(declare (special %x%))
(some-function ...))
然后 %x%
的 symbol-value
在 some-function
的动态范围内仅在适当的线程中是 1
,它可能有一些其他值或未绑定在所有其他线程中。在多个线程 运行 真正并发(例如在多个内核上)的实现中,这意味着 symbol-value
不能 访问 %x%
.
Common Lisp 中符号的单元格绑定似乎没有扩展到 (deftype),是不是 (deftype) 将 [symbol, predicate body] 作为 [key, value] 添加到环境用于类型检查的关联映射中?
我明白为什么类型谓词不会存储在函数单元格中,但是没有 "special operator" 单元格或类型的专用 属性-list 属性是有原因的吗?说明符?
类型信息的存储位置完全取决于实现。某些实现可能会决定使用 symbol-plist。另一个可能会使用一些单独的 table,其中符号只是键。
我不会过多地了解这些细节。
CL 中的类型是 second-class 个对象:没有表示标准语言可用的类型的对象:只有 names of types – 类型说明符。所以很明显,类型没有访问器。此外,CL 中的类型通常根本不是用符号命名的:类型说明符可以是符号、classes 或各种列表。
第一个class 对象代表一些 类型:classes。 类 是 first-class CL中的对象,classes有一个访问器:find-class
。所以,例如
> (typep 1 'integer)
t
> (typep 1 (find-class 'integer))
但是 (find-class '(integer 0))
是一个错误,而 (typep 1 '(integer 0))
是好的(并且是真的)。
请注意,尽管 classes 不是类型:它们是类型 说明符(参见 4.2.3)并且仅适用于有限范围的类型。
符号是否具有 find-class
访问的特殊 'class' 插槽,或者 classes 是否存储在由符号索引的某些 table 中的其他地方,这取决于实现。从历史上看,后者显然是正确的,但至少现在某些实现可能有 class 个插槽。
实际上符号是否有任何槽完全取决于实现:symbol-value
、symbol-function
、symbol-plist
、symbol-package
, symbol-name
&c 可能引用某些 'symbol' 对象中的槽,或者它们可能只是引用由符号索引的 tables,其中符号只是 interned 字符串。当然,有些人会做一个,有些人会做另一个。
一个很好的例子是 symbol-value
:对于声明为特殊的变量 symbol-value
检索其当前动态值:
(let ((%x% 1))
(declare (special %x%))
(symbol-value '%x%))
计算为 1
。
但是有几种可能的方法可以实现这一点:在使用浅绑定的系统中,变量的绑定存储在与符号关联的某个槽中,并且这个槽会随着符号的变化而适当地修改绑定或未绑定,旧绑定存储在某个堆栈中(参见 Henry Baker's paper)。在具有深度绑定的系统中,它不是,绑定是通过搜索绑定堆栈来检索的。朴素的浅绑定系统在存在多线程时会出现相当严重的问题,而朴素的深度绑定系统则不会。使用哪种策略完全取决于实现,当然,这意味着它完全取决于实现 symbol-value
实际做什么以及符号是否有 'value' 个插槽。
我很确定所有使用多线程的实现都做了明显正确的事情:在像
这样的情况下(let ((%x% 1))
(declare (special %x%))
(some-function ...))
然后 %x%
的 symbol-value
在 some-function
的动态范围内仅在适当的线程中是 1
,它可能有一些其他值或未绑定在所有其他线程中。在多个线程 运行 真正并发(例如在多个内核上)的实现中,这意味着 symbol-value
不能 访问 %x%
.