我需要定义函数plPrefixContained
–使用5个字符串,并且
返回第一个包含字符串"pl"
作为前缀的字符串(如果这样的话)
存在,然后返回#f
。
我想做的是使用前缀功能遍历列表中的所有字符串并检查其前缀,将其放入新列表中并输出第一个字符串作为结果。
(我将在以后处理#f
情况)我的代码在下面,但它一直给我错误-
first: contract violation
expected: (and/c list? (not/c empty?))
given: '()
任何帮助将不胜感激
(: plPrefixContained : String String String String String -> String)
(define (plPrefixContained x y z w v)
(list-ref (prefixes (list x y z w v) '()) 0))
(: prefixes : (Listof String) (Listof String) -> (Listof String))
(define (prefixes lis em)
(cond
[(and (eq? (string-ref (first lis) 0) "p") (eq? (string-ref (first lis) 1) "l"))
(cons (first lis) em)]
[else
(prefixes (rest lis) em)]))
这就是我希望输出类似的方式
(test (plPrefixContained "yypl" "opl" "lpTT" "plpl" "lol")
=>
"plpl")
答案 0 :(得分:1)
有两个问题:
eq?
,而不是equal?
或string=?
之类的延伸相等您正在使用eq?
,这总是让我感到怀疑。 eq?
使用“内涵”相等,它基本上是指针相等,这意味着在内存中分配的某个字符串即使具有相同字符也不一定是eq?
。您可以通过(eq? "abc123" (string-append "abc" "123"))
看到它。
如果要处理字符串,列表或任何其他“包含”事物的数据,则应避免使用eq?
。相反,您应该使用“扩展”相等谓词,例如equal?
,或者甚至更好地使用特定于期望值类型的谓词,例如string=?
。它们的行为比eq?
好:
> (eq? "abc123" (string-append "abc" "123"))
#f
> (equal? "abc123" (string-append "abc" "123"))
#t
> (string=? "abc123" (string-append "abc" "123"))
#t
由于您正在使用字符串"p"
和"l"
进行比较,因此我应该能够在代码中用eq?
替换string=?
:
(: prefixes : (Listof String) (Listof String) -> (Listof String))
(define (prefixes lis em)
(cond
[(and (string=? (string-ref (first lis) 0) "p") (string=? (string-ref (first lis) 1) "l"))
(cons (first lis) em)]
[else
(prefixes (rest lis) em)]))
但是,这揭示了第二个问题,只有在看到错误消息后才发现:
string=?: contract violation expected: string? given: #\y argument position: 1st other arguments...: "p"
string=?
不起作用,因为它的第一个参数string-ref
的结果是一个字符(如#\y
),而不是字符串。要解决此问题,请使用char=?
而不是string=?
,并与字符#\p
和#\l
(而不是字符串"p"
和"l"
)进行比较。
(: prefixes : (Listof String) (Listof String) -> (Listof String))
(define (prefixes lis em)
(cond
[(and (char=? (string-ref (first lis) 0) #\p) (char=? (string-ref (first lis) 1) #\l))
(cons (first lis) em)]
[else
(prefixes (rest lis) em)]))