我希望答案为#t
:
> (is-member? "foo" '(4 5 #f "foo" a))
#t
但我收到了错误:
> (is-member? "foo" '(4 5 #f "foo" a))
;string=?: contract violation
; expected: string?
; given: #f
; argument position: 2nd
; other arguments...:
; "foo"
我对is-member?
和is-member-string?
的定义是:
#lang racket
(define (is-member? num lst)
(if (null? lst)
#f
(if (string? num)
(is-member-string? num lst)
(is-member-number? num lst))))
(define (is-member-string? num lst)
(if (null? lst)
#f
(if (integer? (car lst))
(is-member-string? num (rest lst))
(if (string=? (car lst) num)
#t
(is-member-string? num (rest lst))))))
(define (is-member-number? num lst)
....)
答案 0 :(得分:1)
查看错误消息并了解它对您有何帮助。它说错误来自string=?
,如果您查看DrRacket,它甚至会突出显示出错的特定呼叫。它是(string=? (car lst) num)
函数中的is-member-string?
。
弄清楚是什么论点以及为什么他们错了。错误消息表明错误的参数是#f
,它期望一个字符串。
坏的争论来自哪里?是num
还是(car lst)
?查看num
如何在整个计划中流动,num
应始终为"foo"
,因此可能是另一个(car lst)
。
这段代码是如何用错误的参数执行的?为什么(car lst)
在这里是假的?因为它在列表中向下走,列表中包含一个false。这应该没问题,只要你正确设计你的功能来处理所有的值。
为此,您应该在函数上放置一个类型签名,以显示允许哪些类型的参数。对于is-member-string?
,我假设你的意思是:
;; is-member-string? : String [List-of Any] -> Boolean
(define (is-member-string? str lst)
....)
(我已将num
重命名为str
,因为它不是数字,而是字符串。)
接下来,您需要确保代码与签名一起使用。您正在通过解构list参数来设计此函数,但您需要记住值的类型:
;; is-member-string? : String [List-of Any] -> Boolean
(define (is-member-string? str lst)
(if (null? lst)
#f
(.... (first lst) ; (first lst) is an Any
.... (rest lst)))) ; (rest lst) is a [List-of Any]
(我使用first
代替car
,因为first
更有意义。)
你能看到现在的错误吗?
;; is-member-string? : String [List-of Any] -> Boolean
(define (is-member-string? str lst)
(if (null? lst)
#f
(if (integer? (first lst)) ; (first lst) is an Any
(is-member-string? str (rest lst))
(if (string=? (first lst) str) ; (first lst) is an Any, but not an integer
#t
(is-member-string? str (rest lst))))))
(first lst)
是Any
,但您使用的是(string=? (first lst) str)
。除非您确定(first lst)
是一个字符串,否则不应该允许这样做。
有两种方法可以做到这一点。解决此问题的一种方法是使用(equal? (first lst) str)
代替。
;; is-member-string? : String [List-of Any] -> Boolean
(define (is-member-string? str lst)
(if (null? lst)
#f
(if (equal? (first lst) str)
#t
(is-member-string? str (rest lst)))))
第二种方法是在使用string=?
之前检查它是否为字符串。我认为你正在尝试使用integer?
检查,但它无法正常工作。相反,你想以某种方式使用(string? (first lst))
。您只想在通过后检查string=?
。一种方法是使用and
。
;; is-member-string? : String [List-of Any] -> Boolean
(define (is-member-string? str lst)
(if (null? lst)
#f
(if (and (string? (first lst)) (string=? (first lst) str))
#t
(is-member-string? str (rest lst)))))