首先,让我们把事情分解一下。
我们有某种固定价格的产品代码。让我们在函数中处理它
(define (code->price code)
(cond
((equal? code "SST") 20)
((equal? code "LST") 25)
((equal? code "JNS") 70)
(else 999)))
您现在只需调用 (code->price "SST") 即可测试此代码。
请注意,末尾有一个else - 您没有说明无法识别代码时该怎么做。
现在,您似乎有一个包含(CODE QUANTITY) 配对的“订单”列表。请注意,方案中的“对”是与两个项目的列表略有不同的特定事物。您显示的是两个项目的列表,所以我将使用它。
; order = (code quantity) - a list of 2 items
(define (order->price order)
(let ((code (car order))
(quan (cadr order)))
(* quan (code->price code))))
如果我们使用(order->price '("SST" 2)) 进行测试,我们会得到40,这是令人放心的。现在,我们显然只需要一种方法来为我们的订单列表中的每个订单运行它并将结果相加。
(define (recursive-totaller subtot orders)
(if (null? orders)
subtot
(let ((new-subtot (+ subtot (order->price (car orders)))))
(recursive-totaller new-subtot (cdr orders)))))
现在,递归函数在每次调用中都需要相同的“形状”,从第一个调用到最后一个调用。因此,我们将给它一个subtot,第一次调用将为0。如果我们的订单列表为空,那么我们将返回当前subtot将是什么——对于一个空列表,它是0,它是正确的。
如果orders 不为空,我们通过在orders 中的第一项上调用order->price 来计算新的小计。然后我们递归,用新的小计和订单列表的尾部调用我们自己。
假设我们的订单列表不是无限的,我们最终会用一个空列表调用自己,然后通过调用堆栈一直返回最终的小计,直到它到达原始调用者。
(define (test-totaller)
(recursive-totaller 0 '(("SST" 2) ("LST" 1) ("JNS" 3))))
现在,您在“真实”代码中可能不会那么冗长,但老实说,我更喜欢这样的几个函数,它们清楚地知道它们的作用,而不是一个更难理解的更大的函数。
最后 - 将相同的函数应用于列表的所有元素并返回一个新列表是很常见的(称为“映射”),总结列表也很常见(称为“折叠”)和scheme 有帮助你的功能(你可能需要导入“srfi-1”)。
(let* ((orders '(("SST" 2) ("LST" 1) ("JNS" 3)))
(order-prices (map order->price orders)))
(fold + 0 order-prices)))