Racket - 构建内置成员函数

时间:2016-10-12 17:27:21

标签: functional-programming lisp racket sicp

我喜欢编写与内置函数相同的代码。对我来说,这总是很棒的练习。

在球拍中有一个称为“成员”的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: '()

我如何设法处理空?

3 个答案:

答案 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)