我喜欢编写与内置函数相同的代码。对我来说,这总是很棒的练习。
在球拍中有一个称为“成员”的bult-in函数,它检查某个元素是否在列表中。如果为true,则该函数返回列表中的其余/ cdr如果为false,则该函数返回#f。例子:
> (member 2 (list 1 2 3 4))
'(2 3 4)
> (member 9 (list 1 2 3 4))
#f
我做了以下代码:
(require racket/trace)
(define (member-mine lista num)
(cond ((equal? (car lista) num) (cdr lista))
((equal? (car lista) '()) #f)
(else (member-mine (cdr lista) num))))
(define small-list (list 1 2 3 4 5 6 7 8))
(trace member-mine)
而且,当我尝试使用酷工具跟踪时,我部分成功。
通话:
(member-mine small-list 1)
返回:
>(member-mine '(1 2 3 4 5 6 7 8) 1)
<'(2 3 4 5 6 7 8)
通话:
(member-mine small-list 8)
返回:
>(member-mine '(1 2 3 4 5 6 7 8) 8)
>(member-mine '(2 3 4 5 6 7 8) 8)
>(member-mine '(3 4 5 6 7 8) 8)
>(member-mine '(4 5 6 7 8) 8)
>(member-mine '(5 6 7 8) 8)
>(member-mine '(6 7 8) 8)
>(member-mine '(7 8) 8)
>(member-mine '(8) 8)
<'()
问题是当我调用一个不在给定列表中的元素时。输出应为#f:
(member-mine small-list 9)
返回的是错误:
>(member-mine '(1 2 3 4 5 6 7 8) 9)
>(member-mine '(2 3 4 5 6 7 8) 9)
>(member-mine '(3 4 5 6 7 8) 9)
>(member-mine '(4 5 6 7 8) 9)
>(member-mine '(5 6 7 8) 9)
>(member-mine '(6 7 8) 9)
>(member-mine '(7 8) 9)
>(member-mine '(8) 9)
>(member-mine '() 9)
. . car: contract violation
expected: pair?
given: '()
我如何设法处理空?
答案 0 :(得分:3)
您的代码存在一些问题。作为第一个观察,您已经切换合同,以便列表首先而不是最后一个。
您似乎还在检查其中一个元素是否为空列表而不是列表本身。因此,在这种情况下,member
将以#f
终止:
(member-mine '(() 1 2 3 4 5 6 7 8) 1) ; ==> #f
因此,您的会员应检查整个参数是null?
(empty?
)还是检查它是否不是pair?
。然后它应该评估为#f
。
如果第一个元素与您的搜索匹配,那么原始member
将评估整个参数,其中匹配作为第一个元素,而不是代码中的cdr
。
答案 1 :(得分:0)
将空案例移动为条件的第一个分支。当空列表在最终递归调用中传递给您的函数时,您请求列表的car
,由于列表为空,因此无法执行此操作。在调用#f
之前,将空案例置于句子中会导致函数终止car
。
答案 2 :(得分:0)
检查空列表的另一种方法是检查其长度:
(define (member-mine lista num)
(cond
((equal? (length lista) 0) #f) ; '=' can also be used instead of 'equal?'
((equal? (car lista) num) (cdr lista))
(else (member-mine (cdr lista) num))))
(define small-list (list 1 2 3 4 5 6 7 8))
(member-mine small-list 9)
输出:
#f
但正确的方法是:
(empty? lista) or (null? lista)