Racket语言实现指定面额纸币凑数函数的技术问题
解决Racket中calc函数的实现问题
看起来你在写Racket的找零calc函数时遇到了set!相关的问题,我来帮你梳理下~
首先,你的需求是实现一个贪心算法的找零函数,用大面额优先的方式计算每种纸币的使用数量。先给你一个最符合Racket函数式风格的实现,完全不需要用到set!——因为Racket更推荐避免可变状态,递归和不可变数据是更自然的写法:
(define (calc n xs) (if (null? xs) '() (let ([count (quotient n (car xs))] ; 计算当前面额能使用的最大数量 [remaining (remainder n (car xs))]) ; 计算剩余金额 (cons count (calc remaining (cdr xs)))))) ; 递归处理剩余金额和下一个面额
测试你给的示例:
(calc 415 (list 100 10 5 2 1)) ; 返回 '(4 1 1 0 0)
如果你一定要用set!写命令式风格的版本,得注意变量的作用域和绑定规则,下面是正确的写法:
(define (calc n xs) (let ([current-n n] ; 绑定可变的当前金额变量 [result '()]) ; 绑定可变的结果列表变量 (for-each (lambda (x) (let ([count (quotient current-n x)]) (set! result (append result (list count))) ; 更新结果列表 (set! current-n (remainder current-n x)))) ; 更新剩余金额 xs) result))
你可能踩的坑分析
从你给出的代码片段来看,大概率是这几个问题:
begin拼写错误:你写的begi...应该是begin,Racket里需要用begin把多个表达式放在一个分支里执行。set!的作用域问题:如果在cond分支里直接用define定义变量再用set!修改,会因为作用域限制导致变量无法被正确修改——set!只能修改当前或外层作用域已经绑定好的变量,不能修改分支内局部定义的变量(得先用let提前绑定可变变量)。- 思维转换不到位:Racket是函数式语言,强行用
set!写命令式代码反而容易出错,递归写法更贴合语言设计。
内容的提问来源于stack exchange,提问作者SyntaxIsNotTheProblem
相关产品推荐
相关产品推荐

