我试图检查列表中的第一个原子与列表中的其他原子,所以如果第一个原子是3而第三个原子是3,我想将它评估为假。
我有类似
的东西 (define (doubles a_list)
(cond
((null? a_list) #t)
(not ((eq? (car a_list) (car (cdr a_list)))) (doubles(cdr a_list)))
我有一种感觉,这只会检查彼此相邻的原子而不是其他原子的原子。我该怎么做才能检查第一个项目?
答案 0 :(得分:2)
您希望反复比较列表的前两个元素,减少cdr
:
(define (unique-first? x)
; uncomment the following line to trace the execution
;(display x) (newline)
(or (null? x) (null? (cdr x))
(and (not (eq? (car x) (cadr x)))
(unique-first? (cons (car x) (cddr x))))))
特殊情况说明:
(unique-first? '())
- > #t
(unique-first? '(a))
- > #t
(确实,确认"第一个元素不会出现两次"标准)。
答案 1 :(得分:1)
我有茶,我的代码审查帽和几分钟。你知道现在几点了。
你想要的是一个谓词,它会告诉你列表中第一个原子是否有重复。
(define (doubles a_list)
(cond ((null? a_list) #t)
(not ((eq? (car a_list) (car (cdr a_list)))) (doubles(cdr a_list)))
无论如何,这都行不通,因为它有不平衡的括号。
(define (doubles a_list)
(cond ((null? a_list) #t)
(not ((eq? (car a_list) (car (cdr a_list)))) (doubles(cdr a_list)))))
该修订版本无效,因为case
中的第二个条款格式错误。奇怪的是,它似乎评价很好,但是当你调用它时,你会得到一个奇怪的错误信息
Welcome to Racket v5.3.6.
> (define (doubles a_list)
(cond ((null? a_list) #t)
(not ((eq? (car a_list) (car (cdr a_list)))) (doubles(cdr a_list)))))
> (doubles (list 1 2 3 4 5 6 7 3))
application: not a procedure;
expected a procedure that can be applied to arguments
given: #f
arguments...: [none]
>
直接原因是这一点
... ((eq? (car a_list) (car (cdr a_list)))) ...
由于这个表达式周围有额外的parens,它实际意味着什么
“查看
a_list
的第一个元素是否与第二个元素相同,然后将该检查的结果称为函数”。
这不是你想要的。正确的解决方案是将not
放入这些parens中,这将使其成为有效的cond
子句。
(define (doubles a_list)
(cond ((null? a_list) #t)
((not (eq? (car a_list) (car (cdr a_list))))
(doubles (cdr a_list)))))
您无法在Scheme中的空列表中调用car
。对于Common Lisp中的“fine”的某些定义,这样可以正常工作,但会在这里引发错误。
> (define (doubles a_list)
(cond ((null? a_list) #t)
((not (eq? (car a_list) (car (cdr a_list))))
(doubles (cdr a_list)))))
> (doubles (list 1 2 3 4 5 6 7 3))
car: contract violation
expected: pair?
given: '()
>
此错误的原因是您要检查a_list
是null?
,还是稍后再调用(car (cdr a_list))
。在a_list
类似于(3)
的情况下,您会收到此错误。对此的修复是检查a_list
或其cdr
是null?
(define (doubles a_list)
(cond ((or (null? a_list) (null? (cdr a_list))) #t)
((not (eq? (car a_list) (car (cdr a_list))))
(doubles (cdr a_list)))))
> (doubles (list 1 2 3 4 5 6 7 3))
#t
现在我们已经有了一个不会出错的函数版本,让我们来看看你的逻辑。在列表中查找双精度的过程是
现在,您已将您的函数命名为doubles
,但您的散文解释告诉我它确实应该是unique-first?
。因为您不是在寻找双打,所以您需要检查列表中的第一个元素是否在同行中是唯一的。你真正想做的是
转换为
(define (unique-first? a_list)
(if (or (null? a_list) (null? (cdr a_list)))
#t
(not (member? (car a_list) (cdr a_list)))))
member?
函数非常简单,并且基于相同的原则。
(define (member? elem lst)
(cond ((null? lst) #f)
((eq? elem (car lst)) #t)
(else (member? elem (cdr lst)))))
最后,有几个风格点。 Scheme约定是使用尾随?
来命名谓词,它会向你的函数调用者提示它将返回#t
或#f
(我已经在上面做过),并且使用spinal-case
而不是snake_case
作为名称。
(define (unique-first? a-list)
(if (or (null? a-list) (null? (cdr a-list)))
#t
(not (member? (car a-list) (cdr a-list)))))