我想在Scheme中编写一个代码,用于写入list中的square奇数元素。例如(list 1 2 3 4 5)这个列表应该写225.为此,我编写了这段代码:
(define (square x)(* x x))
(define (product-of-square-of-odd-elements sequence)
(cond[(odd? (car sequence)) '() (product-of-square-of-odd-elements (cdr sequence))]
[else ((square (car sequence)) (product-of-square-of-odd-elements (cdr sequence)))]))
对于跑步我写这个(product-of-square-of-odd-elements (list 1 2 3 4 5))
我得到这样的错误:
car: contract violation
expected: pair?
given: '()
如何使此代码正常运行?谢谢你的回答。
答案 0 :(得分:2)
首先,您需要进行适当的格式化:
(define (square x) (* x x))
(define (product-of-square-of-odd-elements sequence)
(cond
[(odd? (car sequence))
'() (product-of-square-of-odd-elements (cdr sequence))]
[else
((square (car sequence)) (product-of-square-of-odd-elements (cdr sequence)))]))
现在您的代码存在多个问题:
您正在尝试以递归方式处理序列,但您错过了终止案例:当您传递'()
- 空序列时会发生什么?这是您的错误的来源:您无法访问空序列的第一个元素。
你需要以某种方式建立你的结果:目前你在'()
的第一个分支中发送cond
进入必杀技,并将值放入函数调用位置第二个。
所以让我们从头开始:
您以递归方式处理序列,因此需要处理两种情况:
(define (fn seq)
(if (null? seq)
;; termination case
;; recursive case
))
首先考虑递归情况:你需要计算平方并将其乘以其余的正方形(你接下来要计算)。
(* (if (odd? (car seq)
(square (car seq))
1)
(fn (cdr seq)))
在终止案例中,你没有任何价值。所以你只需使用乘法的单位值:1
这不是一个好的解决方案,因为您可以将其转换为尾递归形式,并使用更高阶函数来完全抽象递归。但我认为这对于一个开始就足够了。
答案 1 :(得分:1)
您可以将问题分解为,例如:
有了这个,实现自然地使用更简单的函数(大多数存在于Scheme中)表示为:
(define product-of-square-of-odd-elements (l)
(reduce * 1 (map square (skip-every-n 1 l))))
然后实现一两个辅助函数,如skip-every-n
。
答案 2 :(得分:1)
使用transducers:
(define prod-square-odds
(let ((prod-square-odds
((compose (filtering odd?)
(mapping square)) *)))
(lambda (lst)
(foldl prod-square-odds 1 lst))))
(prod-square-odds '(1 2 3 4 5))
; ==> 225
它使用可重复使用的传感器:
(define (mapping procedure)
(lambda (kons)
(lambda (e acc)
(kons (procedure e) acc))))
(define (filtering predicate?)
(lambda (kons)
(lambda (e acc)
(if (predicate? e)
(kons e acc)
acc))))