word->字符串导致eq问题?

时间:2017-09-28 23:21:14

标签: string scheme

我正在尝试在(简单)方案中创建一个游戏,其中read-line接受用户的输入并做相应的事情。要进行问题排查,我使用trace查看我的每个程序都在“思考”:

(trace eq?)
(trace string-downcase)
(trace word->string)
(trace first)
(trace read-line)

现在,当我向read-line请求“是”时,会发生以下情况:

> (eq? (string-downcase (word->string (first (read-line)))) "yes")
>(read-line)
yes
<'(yes)
>(first '(yes))
<'yes
>(word->string 'yes)
<"yes"
>(string-downcase "yes")
<"yes"
>(eq? "yes" "yes")
<#f
#f

当我单独运行(eq? "yes" "yes")时,它会像它应该的那样返回#t,但在这里它不是出于某种原因。我怀疑它与word->string的定义有关。这完全打破了我的游戏;如果用户输入yes,则表明他们会输入no。请告诉我你为什么会这样做的任何想法!

2 个答案:

答案 0 :(得分:2)

  

当我单独运行(eq? "yes" "yes")时,会返回#t,就像它应该

一样

没有。你的假设是错误的。 eq? 保证在字符串上有任何特定行为。

R 5 RS在非空字符串上定义eq?以使用与eqv?相同的规则。反过来,eqv? #t必须在两个字符串上返回eq? obj 1 obj 2 ,时间:

  

obj 1 obj 2 是表示相同位置的对,向量或字符串商店(it states}部分。

“商店”的概念定义非常宽松,与实现有关。基本上,字符串上的equal?是实现定义的。您几乎总是希望string=?执行实际值相等(而不是引用相等),或int,它专门检查字符串上的相等性。

答案 1 :(得分:1)

字符串存储为字符向量。 eq?是标识过程,因此它检查两个参数是否是同一个对象。多个变量指向同一个Object,因此在单个线程实现的一个时刻创建,是eq?

有一个例外。代码中的文字可以被缓存,使得每次创建时创建的对象可以在代码中的每次出现时生成一次。其他语言也是如此,例如。 Java有一个字符串文字池,其中"yes" == "yes"true但当然("y" + "es") == "yes"false,因为左边是一个具有相同字符的新字符串而不是与文字池中的"yes"相同的对象。

所有文字都是如此。与'(some list)进行比较的"some literal string"eq?可能会给#t #f,如果在运行时创建了一侧而不是文字,那么make-string就是答案。 (例如list)或eqv?

经验法则

使用=或特殊数字比较程序(<#f,...)作为数字。数字是唯一允许实现在任何时间将值复制到不同形式的数据类型,因此即使它看起来像是同一个对象,相同的数字也可能是eq? eqv?。对于#t的每次比较,eq?保证为eq?

如果您想知道是否同时创建了两件事,则使用eq?的数字除外。 (同一个对象)。例如。从一个看到元素的关联中的树中查找特定节点是典型的#t时刻。对于相同的符号,符号是唯一保证为equal?的文字。

如果你想知道两件事情是否相同,你应该使用equal?。对于#t的每次比较,eqv?保证为string=?。如果您确定自己有字符串,可以使用equal?进行区分大小写的比较(如string-ci=?确实)和"yes"进行不区分大小写的比较。

请注意,字符串和符号看起来不一样。一个在REPL中具有yes形式和另一个"~\.(..)\.~g" 形式。