我正在尝试在(简单)方案中创建一个游戏,其中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
。请告诉我你为什么会这样做的任何想法!
答案 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"
形式。