必ず使用する必要があります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 でプログラミングする慣用的な方法です - ミューテーション操作を使用しません。C のような言語でこの問題を解決する方法と同様に、手続き型のソリューション (@GoZoner の回答を参照) を作成することもできますが、それは慣用的ではありません。