Racket 情商如何?在球拍中使用符号和数字?
Racket文档告诉我“如果Racket 情商如何?在球拍中使用符号和数字?,racket,Racket,Racket文档告诉我“如果v1和v2引用同一个对象,eq?返回“如果所有参数在数值上相等,返回\t”两个修饰符也相同。我找不到任何关于“数字”和“符号”的信息,但在示例中我发现: >(等式?'yes'yes) #t 这与上面的说法相矛盾,因为上面从未提到过符号是特殊的,所以'yes和'yes是不同的 这让我更加困惑: >(等式?(expt 2100)(expt 2100)) #f >(等式?(*67)42) #t 如果数字是通过数字测试的,那么(eq?(expt 2 100)(expt 2
v1
和v2
引用同一个对象,eq?
返回
”,但是根据eq?
,=/code>“如果所有参数在数值上相等,返回\t
”两个修饰符也相同。我找不到任何关于“数字”和“符号”的信息,但在示例中我发现:
>(等式?'yes'yes)
#t
这与上面的说法相矛盾,因为上面从未提到过符号
是特殊的,所以'yes
和'yes
是不同的
这让我更加困惑:
>(等式?(expt 2100)(expt 2100))
#f
>(等式?(*67)42)
#t
如果数字是通过数字测试的,那么(eq?(expt 2 100)(expt 2 100))
应该返回#t
,否则,数字是通过引用测试的,那么(eq(?6 7)42)
应该返回#f
,所以我猜以上两种情况都不对
为什么
太大,无法成为fixnum
。让我们试着评估一下:
(expt 2 100) ; => 1267650600228229401496703205376
(fixnum? (expt 2 100)) ; => #f
(expt 2 10) ; => 1024
(fixnum? (expt 2 100)) ; => #t
这是因为在几个存储单元中分配了大量的数字(将它们看作是一组数字的列表)
另一方面,每个符号在阅读时都是“内在化”的。这意味着第一次读取时,将为其创建一个新的符号值。随后,当再次读取时,系统检查具有该名称的符号是否已经存在,在这种情况下,返回旧符号值,而不在内存中创建任何新对象。因此:
(eq 'yes 'yes) ; => #t
因为显然是两个不同的符号,具有相同的名称,实际上是内存中的同一对象。这是在@Renzo的答案之外提供额外的信息
如何检查数据类型是否“内部化”
答案是这很复杂
一个因素是:
读取器在读取语法
模式下生成的符号、关键字、字符串、字节字符串、regexp、字符和数字都被插入,这意味着读取语法
结果中的这些值在相等时总是eq?
(无论是来自对读取语法的相同调用还是不同调用)。符号和关键字在读取
和读取语法
模式下都被插入。通过place频道发送插入值不一定在接收地点产生插入值。另请参见数据插入文字
和数据->语法
因此(eq?(expt2100)(expt2100))
返回#f
,因为(expt2100)
需要在运行时计算。另一方面,(eq?1267650600228229401496703205376 1267650600228229401496703205376)
返回#t
,因为该值在读取时是明显的,允许Racket插入该数字
另一个因素是数据类型
根据eq?
,属于=
的两个修饰符也是相同的。否则,应用于两个数字的eq?
的结果是未定义的
这意味着(等式(+12)3)
保证是#t
符号通常是插入的,但也可以通过string->unterned symbol
和gensym
进行插入
一个符号就像一个不可变的字符串,但符号通常是内部的,因此具有相同字符内容的两个符号通常相等
这两个过程string->Unterned symbol和gensym生成了Unterned symbol,即,与任何其他符号不相等、不相等的符号,尽管它们可能与其他符号打印相同
因此:
谢谢,我可能理解,但是我如何检查一个数据类型是否“内部化”?它仅仅取决于它是否分配到多个内存单元中?
(eq 'yes 'yes) ; => #t
> (eq? (string->symbol "ab") (string->symbol (string-append "a" "b")))
#t
> (eq? (string->uninterned-symbol "ab") (string->uninterned-symbol "ab"))
#f