我在这里开始提出一个关于我正在进行的刽子手游戏的问题。
Recursive Scheme Function Value Error
我觉得刽子手部分让人们对我的真实问题和疑问感到困惑。我的问题是,我在递归循环中调用各种已定义的函数并获取不正确的值。当我自己调用这些相同的函数时(不是在递归循环中),它们按预期工作。我知道这是我要忽视的东西,或者是一个变量绑定问题,我需要一个解决方法。
首先是问题代码的再现:
(define (recurse a_list a_number)
(cond ((= a_number 0)
(display "Zero Condition.")
)
(else
(display "\n\n")
(display-list a_list ",")
(display "\n")
(display (car a_constant))
(display "\n")
(display "If the above letter is in the list, result should be true\n")
(display (contains? a_list (car a_constant)))
(display "\n")
(display "Enter a letter:")
(recurse (cons (symbol->string (read)) a_list) (- a_number 1))
)
)
)
以下是我在递归循环中使用的定义:
(define (display-list a_list separater)
(if (null? a_list)
(display "")
(begin
(display (car a_list))
(if (null? (cdr a_list))
(display "")
(display separater))
(display-list (cdr a_list) separater)
)
)
)
(define (contains? list item)
;(display "\n")
;(display list)
;(display "\n")
;(display item)
;(display "\n")
(cond ((empty? list)
#f
)
((eq? (first list) item)
#t
)
(else
(contains? (rest list) item)
)
)
)
(define a_constant '("n" "o" "t" "w" "o" "r" "k" "i" "n" "g"))
(define test_li_1 '("n" "b"))
(define test_li_2 '("a" "b"))
这就是我的目的:
> (contains? a_constant (car test_li_1))
#t
> (contains? a_constant (car test_li_2))
#f
它按预期工作。
当我运行递归循环时,这就是我得到的:
> (recurse test_li_2 2)
a,b
n
If the above letter is in the list, result should be true
#f
Enter a letter:n
n,a,b
n
If the above letter is in the list, result should be true
#f
在我看来,第一个输出是正确的,但第二个输出不是。
当我使用test_li_1运行时,它总是评估为true,它应该是' n'总是在我的a_list中。我通过几个测试放在一起的是递归函数继续使用我最初传入的列表并且不使用附加版本进行函数调用,这不是我想要它做的。我也认为这不是它应该如何正常工作?不应该使用我传入的值而不是几个递归级别的值吗?如果重要的话,我会用#lang球拍对Dr.Batet博士进行测试。
答案 0 :(得分:4)
报告的问题是因为您使用eq?
来测试字符串相等性。来自文档:
(eq? v1 v2) → boolean?
:如果#t
和v1
引用相同的对象,则返回v2
,否则返回#f
。
所以你看,eq?
正在测试身份,而不是相等。为此,您应该使用string=?
或equal?
。修改contains?
程序,如下所示,它将起作用:
(define (contains? list item)
(cond
((empty? list) #f)
((string=? (first list) item) #t)
(else (contains? (rest list) item))))
答案 1 :(得分:2)
当您致电(symbol->string (read))
并输入a
时,您会收到新字符串" a"。这是一个新的字符串对象不是eq?到任何" a"在你的程序中。试试看这个问题:
(eq? (symbol->string (read)) "a")
如果您输入a
,则会输出#f
,因为这两个字符串项是单独的对象。您已经与字符串实习发生冲突。 " a"的所有实例写在源代码中的内容在编译时存储为对一个对象的引用,因此(eq? "a" "a")
将评估为true。当您(read)
作为字符串输入时,这些字符串将是新创建的对象,并且不会等于任何其他字符串。有两种方法可以解决这个问题:
string=?
代替eq?
进行比较(如在奥斯卡的回答中)使用字符列表而不是单字符字符串列表,例如'(#\a #\b #\c)
是字符串" abc"。来自Racket documentation of characters:
两个字符是eqv?如果它们对应于相同的标量值。对于每个小于256的标量值,字符值是eqv?也是eq?
字母字符(a-z和A-Z)在Racket的Unicode编码中的值小于此值,因此read
中的任何字母字符都不会与eq?
问题发生冲突。这提出了另一点 - 您应该从read
清理您的输入。 read
过程不保证返回字符串,特别是如果我输入1而不是字符串,则返回数字1,而不是字符串" 1&#34 ;。您应该添加一些逻辑来处理错误输入,否则会导致程序崩溃。