新年快乐!
我正在工作,我的球拍(不是一个解释李斯特)。
现在我在球拍8.3中遇到了以下情况:
#lang racket
> (define str1 "hello")
> (define str2 "hello")
> (eq? str1 str2)
#t我以为#f喜欢这里。在Guile和Common中,这是返回的。
根据这,我可以按照预期再现以下行为:
> (set! str1 (string #\h #\e #\l #\l #\o))
> (set! str2 (string #\h #\e #\l #\l #\o))
> (eq? str1 str2)
#f但我不明白原因。
是吗,在球拍中只有函数字符串返回两个不同的对象,而文字字符串像符号一样是唯一的?因此,eq?通常情况下,文本字符串的处理方式不同吗?
你能对我解释一下吗?
非常感谢。
发布于 2022-01-02 13:24:25
eq?所做的与eq在公共Lisp中所做的事情是一样的:它告诉您两个对象是否是同一个对象。
您所看到的是,通常没有定义相似的文字对象是否实际上是相同的对象,而使它们相同往往会有好处。一个特别的好处是这样可以减少内存的使用。
在球拍的情况下,文字字符串显然是这样合并的,至少在某些情况下是这样的。(但并非总是这样:给定以下程序
#lang racket
(define (ts)
(define (getit prompt)
(printf "~S? " prompt)
(read))
(eq? (getit "1")
(getit "2")))
(ts)然后
$ racket ts.rkt
"1"? "foo"
"2"? "foo"
#f例如)
一般来说,您不应该假设类似的文字实际上是否是相同的对象,因为系统可能选择或不选择将它们结合在一起,而且在任何特定情况下都可能选择这样做,或者不选择这样做。
例如,在CL中,如果您有一个包含此函数的文件
(defun foo ()
(eq "foo" "foo"))然后编译该文件,它只是完全和显式地未定义该函数是返回true还是false:即使READ为这两个字符串返回不同的对象(我不确定需要这样做,但它可能需要这样做),文件编译器肯定允许合并它们,所以只有一个文本字符串(当然,它可以注意到函数总是返回true并简单地将其转换为(defun foo () t))。
因此,答案是:永远不要假设文本是相同的,或者是相同的,或者不是相同的:如果你想要相似但不完全相同的对象,你需要用一个函数来定义它们来创建新的对象。
发布于 2022-01-03 04:23:11
是吗,在球拍中只有函数字符串返回两个不同的对象.
不仅仅是函数string。几乎每个字符串函数,比如string-append,都可以创建两个不同的对象:
(define a "a")
(eq? (string-append a a) (string-append a a)) ;=> #f..。文字字符串就像符号一样独特吗?因此,eq?通常情况下,文本字符串的处理方式不同吗?
对于球拍,是的,这在文档中是有保证的
默认读取器(请参阅读字符串)生成的字符串常量是不可变的,它们在读-语法模式下被嵌入。
为了更详细地介绍一下,Racket使用read-syntax来读取您的程序,并在read-syntax中进行字符串读取。
(define a (syntax-e (read-syntax))) ; input "a"
(define b (syntax-e (read-syntax))) ; input "a"
(eq? a b) ;=> #t发布于 2022-01-04 19:37:48
标准不想指定实现术语,而是列出了什么应该是#t,什么应该是#f,以及eq?始终都是eqv?,反之亦然。除了指针均匀度这一关键信息外,他们什么都写。即。当两个参数是相同的对象时,eq?返回#t,比如Java的==。
在方案中,未指定(eq? "a" "a")。#t和#f都是可以接受的结果。它是报告中的例子之一。像"a"或'(a b c)这样的文字值是不可变的。这将从引号引用到有关存储模型的信息。
在同一份报告中,试图更改文本被认为是一个错误。在string-set!中,如下所示:
(define (f) (make-string 3 #\*))
(string-set! (f) 0 #\?) ⇒ unspecified因此,make-string生成一个新的字符串,每个调用都不能使用,所以第一个示例是使用周期的OK Scheme代码。如果要将结果绑定到一个变量,然后执行它,您将可以访问如下所示的结果:
(define (f) (make-string 3 #\*))
(define test (f))
(string-set! test 0 #\?) ⇒ unspecified
test ⇒ "?**"现在,第二个示例将更多地讨论主题。
(define (g) "***")
(string-set! (g) 0 #\?) ⇒ unspecified
; should raise &assertion exceptionR5RS甚至说它甚至都不是Scheme,所以任何结果都是可以的,而R6RS和后来强烈建议尝试变异应该会引发一个例外。
对于那些调用(g)的人来说,大多数实现都不是这样的,当非法代码正常工作时,很可能会导致"?**"或"***"中的一个错误。
请回到您的代码:
(define str1 "hello")
(define str2 "hello")
(eq? str1 str2) ⇒ unspecified出于完全相同的原因,未指定(eq? "a" "a")。解释器可能总是返回#f,甚至返回编译过的代码,但是编译后的代码更有可能返回#t。
(define str1 (string #\h #\e #\l #\l #\o))
(define str2 (string #\h #\e #\l #\l #\o))
(eq? str1 str2) ⇒ #f它们总是不同的,因为(string #\h #\e #\l #\l #\o)创建了一个新字符串,而且由于str1和str2是分开创建的,所以它们是不同的字符串,看起来是相同的。
要知道,这样的复合数据类型可以与equal?检查是否相等,在两个对象被认为相同时返回#t,例如。通常是当他们看起来一样的时候。因此:
(equal? str1 str2) ⇒ #thttps://stackoverflow.com/questions/70555419
复制相似问题