我正在学习积累和折叠,但我的代码中的某些内容是错误的。我想比较所有列表中的元素,但foldr只使用第一个和第二个元素。这是我的代码:
(define accum?
(lambda (list1 pre?)
(foldr (lambda (x y)
(if (pre? (car list1) (cadr list1)) #t #f))
#f
list1)))
(accum? '(1 2 3 4) <) --> #t
(accum? '(3 2 3 4) <) --> #f
(accum? '(1 2 5 4) <) --> #t (should be #f)
(accum? '(5 7 2 3) <) --> #t (should be #f)
你知道哪里出错吗?顺便说一句,最好只使用(pre?(car list1)(cadr list1))而不使用if - &gt; (如果&lt; ...&gt; #t #f)?
答案 0 :(得分:2)
使用apply
,使用比较运算符接收可变数量的参数这一事实可以更轻松地解决此问题:
(apply < '(1 2 3 4))
=> #t
(apply < '(1 2 5 4))
=> #f
<强>更新强>
特别是对于这个问题,foldr
不适合这项工作(虽然这不是不可能的,因为你demonstrated) - 没有值“累积”在遍历列表时,对于给定的谓词,列表是否有序。
根据评论,我了解pre?
程序可以是任意lambda
,只能接收两个参数。
一种可能的解决方案是创建所有连续元素对的列表,并检查谓词是否适用于所有这些元素。请注意,最后一个元素没有对应的对,因此我们需要将它从对列表中排除。为此,我将定义一个特殊的zip
过程,给定两个输入列表,考虑到列表可以具有不同长度这一事实,创建一个对列表:
(define (zip lst1 lst2)
(if (or (null? lst1) (null? lst2))
'()
(cons (list (car lst1) (car lst2))
(zip (cdr lst1) (cdr lst2)))))
(zip '(1 2 3) '(2 3))
=> '((1 2) (2 3))
现在把所有这些放在一起,我们可以像这样解决原来的问题:
(define (accum? lst pre?)
(andmap (lambda (tuple)
(pre? (car tuple) (cadr tuple)))
(zip lst (cdr lst))))
请记住,它不适用于空列表,但为此添加一个特殊情况是微不足道的。现在可以使用任意lambdas
:
(accum? '(1 2 3) (lambda (a b) (= a (- b 1))))
=> #t
答案 1 :(得分:0)
它只使用第一个和第二个元素,因为你明确地使用(car list1)
和(cadr list1)
来获取第一个和第二个元素。
请注意,当您实际上没有使用x
和y
时,传递给lambda的参数。这肯定表明你做错了什么。
PS:这与您的问题无关,但写(if condition #t #f)
与编写condition
几乎完全相同。所以是的,遗漏if
会更好,因为它没有用处。