Dem*_*ame 2 lisp comparison scheme racket
新年快乐!
我正在努力进入 Racket(我不是一个经验丰富的 Lisper)。
现在我在 Racket 8.3 中遇到了以下内容:
#lang racket
> (define str1 "hello")
> (define str2 "hello")
> (eq? str1 str2)
#t
Run Code Online (Sandbox Code Playgroud)
我期待#f像这里一样。在 Guile 和 Common Lisp 中,这被返回。
据此,我可以重现以下行为符合预期:
> (set! str1 (string #\h #\e #\l #\l #\o))
> (set! str2 (string #\h #\e #\l #\l #\o))
> (eq? str1 str2)
#f
Run Code Online (Sandbox Code Playgroud)
但我不明白原因。
是不是,在 Racket 中,只有函数 STRING 返回两个不同的对象,而文字字符串却像符号一样是唯一的?因此,等式?行为通常,但文字字符串的处理方式有所不同?
你能好心给我解释一下吗?
非常感谢。
其eq?
作用与 Common Lisp 中的作用相同eq
:它告诉您两个对象是否是同一个对象。
您所看到的是,通常无法定义相似的文字对象是否实际上是同一对象,并且使它们相同通常会带来好处。一个特别的好处是,这样可以使用更少的内存。
对于 Racket 来说,很明显,文字字符串是这样合并的,至少在某些情况下是这样。(但并非总是如此:给定以下程序
#lang racket
(define (ts)
(define (getit prompt)
(printf "~S? " prompt)
(read))
(eq? (getit "1")
(getit "2")))
(ts)
Run Code Online (Sandbox Code Playgroud)
然后
$ racket ts.rkt
"1"? "foo"
"2"? "foo"
#f
Run Code Online (Sandbox Code Playgroud)
例如。)
一般来说,您不应该假设相似的文字实际上是否是同一个对象,因为系统可能会也可能不会选择合并它们,并且在任何特定情况下可能会也可能不会选择这样做。
举个例子,在 CL 中,如果您有一个包含此函数的文件
(defun foo ()
(eq "foo" "foo"))
Run Code Online (Sandbox Code Playgroud)
当你编译该文件时,无论该函数返回 true 还是 false,它都是完全明确未定义的:即使为READ
两个字符串返回不同的对象(我不确定是否需要这样做,但可能是),文件编译器是当然允许合并它们,因此只有一个文字字符串(当然,因此允许注意到该函数总是返回 true 并简单地将其转换为(defun foo () t)
)。
所以答案是:永远不要对相似的文字做出假设,无论是相同还是不同:如果您想要相似但不相同的对象,您需要使用定义为创建新对象的函数自己创建它们。