Racket - 构建内置成员函数
Racket - Building the built-in member function
我喜欢编写与内置函数相同的代码。这对我来说总是很好的锻炼。
racket 中有一个名为 "member" 的内置函数,它检查某个元素是否在列表中。如果为真,则函数 returns rest/cdr o 列表 如果为假,则函数 returns #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)
Returns:
>(member-mine '(1 2 3 4 5 6 7 8) 1)
<'(2 3 4 5 6 7 8)
通话中:
(member-mine small-list 8)
Returns:
>(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)
其中returns是一个错误:
>(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: '()
如何处理空的?
将空格移动到条件的第一个分支。当空列表在最后的递归调用中传递给您的函数时,您请求列表的 car
,这无法完成,因为列表是空的。将空 case 放在拳头上应该会导致函数在到达对 car
.
的调用之前以 #f
终止
您的代码存在一些问题。作为第一个观察结果,您已经切换了合同,以便列表排在第一位而不是最后一位。
您似乎也在检查其中一个元素是否为空列表而不是列表本身。因此,在这种情况下,您的 member
将以 #f
终止:
(member-mine '(() 1 2 3 4 5 6 7 8) 1) ; ==> #f
因此您的成员应该检查整个参数是否为 null?
(empty?
)或者检查它是否不是 pair?
。然后它应该评估为 #f
.
如果第一个元素与您的搜索相匹配,那么原始 member
计算整个参数并将匹配作为第一个元素,而不是像您的代码中那样 cdr
。
另一种检查空列表的方法是检查它的长度:
(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)
我喜欢编写与内置函数相同的代码。这对我来说总是很好的锻炼。
racket 中有一个名为 "member" 的内置函数,它检查某个元素是否在列表中。如果为真,则函数 returns rest/cdr o 列表 如果为假,则函数 returns #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)
Returns:
>(member-mine '(1 2 3 4 5 6 7 8) 1)
<'(2 3 4 5 6 7 8)
通话中:
(member-mine small-list 8)
Returns:
>(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)
其中returns是一个错误:
>(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: '()
如何处理空的?
将空格移动到条件的第一个分支。当空列表在最后的递归调用中传递给您的函数时,您请求列表的 car
,这无法完成,因为列表是空的。将空 case 放在拳头上应该会导致函数在到达对 car
.
#f
终止
您的代码存在一些问题。作为第一个观察结果,您已经切换了合同,以便列表排在第一位而不是最后一位。
您似乎也在检查其中一个元素是否为空列表而不是列表本身。因此,在这种情况下,您的 member
将以 #f
终止:
(member-mine '(() 1 2 3 4 5 6 7 8) 1) ; ==> #f
因此您的成员应该检查整个参数是否为 null?
(empty?
)或者检查它是否不是 pair?
。然后它应该评估为 #f
.
如果第一个元素与您的搜索相匹配,那么原始 member
计算整个参数并将匹配作为第一个元素,而不是像您的代码中那样 cdr
。
另一种检查空列表的方法是检查它的长度:
(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)