Scheme 在迭代期间从条件创建列表

Scheme 在迭代期间从条件创建列表,scheme,Scheme,我已经写了一个简单的程序来寻找一个数字的除数(不包括数字本身)。我已经知道了如何打印它们,但是我想让这个函数返回一个包含每个除数的列表 (define (divisors n) (do ((i 1 (+ i 1))) ((> i (floor (/ n 2)))) (cond ((= (modulo n i) 0) (printf "~a " i))))) 我的想法是创建一个本地列表,将元素添加到printf表达式所在的位置,然后

我已经写了一个简单的程序来寻找一个数字的除数(不包括数字本身)。我已经知道了如何打印它们,但是我想让这个函数返回一个包含每个除数的列表

(define (divisors n)

  (do ((i 1 (+ i 1)))    
    ((> i (floor (/ n 2))))
    (cond 
      ((= (modulo n i) 0)
       (printf "~a " i)))))

我的想法是创建一个本地列表,将元素添加到printf表达式所在的位置,然后让函数返回该列表。我该怎么做呢?我是Scheme和Lisp的新手。

您一定要使用吗?这里有一个方法:

(define (divisors n)
  (do ((i 1 (add1 i))
       (acc '() (if (zero? (modulo n i)) (cons i acc) acc)))
    ((> i (floor (/ n 2)))
     (reverse acc))))
但我相信,如果您建立一个带有以下内容的输出列表,则更容易理解:

或者,如果您碰巧使用球拍,您可以这样使用:

(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的语言解决这个问题,但这不是惯用的方法。

只需创建一个局部变量
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
都“consed”在
l
的前面,因此
l
中的顺序将从高到低。如果需要从低到高的顺序,则使用
(反向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))