你一定要使用必须使用do
吗?这是一种方法:
(define (divisors n)
(do ((i 1 (add1 i))
(acc '() (if (zero? (modulo n i)) (cons i acc) acc)))
((> i (floor (/ n 2)))
(reverse acc))))
但我相信如果您使用命名let
构建输出列表会更容易理解:
(define (divisors n)
(let loop ((i 1))
(cond ((> i (floor (/ n 2))) '())
((zero? (modulo n i))
(cons i (loop (add1 i))))
(else (loop (add1 i))))))
或者如果你碰巧在使用 Racket,你可以for/fold
这样使用:
(define (divisors n)
(reverse
(for/fold ([acc '()])
([i (in-range 1 (add1 (floor (/ n 2))))])
(if (zero? (modulo n i))
(cons i acc)
acc))))
请注意,上述所有解决方案都是以函数式编程风格编写的,这是在 Scheme 中编程的惯用方式 - 不使用变异操作。也可以编写程序风格的解决方案(请参阅@GoZoner 的答案),类似于您使用类 C 语言解决此问题的方式,但这不是惯用的。