我写了一个简单的程序来查找数字的除数(不包括数字本身)。我已经想出了如何打印它们,但是我想让这个函数返回一个包含每个除数的列表。
(define (divisors n)
(do ((i 1 (+ i 1)))
((> i (floor (/ n 2))))
(cond
((= (modulo n i) 0)
(printf "~a " i)))))
我的想法是创建一个本地列表,向我的printf表达式添加元素,然后让函数返回该列表。我该怎么做呢?我是Scheme的新手,也是Lisp的新手。
答案 0 :(得分:1)
您是否必须使用必须使用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))))
但我相信如果您使用named 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语言解决这个问题的方法,但这不是惯用的
答案 1 :(得分:1)
只需创建一个局部变量l
并扩展它而不是打印东西。完成后,返回它。像这样:
(define (divisors n)
(let ((l '()))
(do ((i 1 (+ i 1)))
((> i (floor (/ n 2))))
(cond ((= (modulo n i) 0)
(set! l (cons i l))))
l))
请注意,因为i
的前面l
被“强制”,所以l
中的排序会从高到低。如果需要从低到高的顺序,请使用(reverse l)
作为返回值。