为什么在Racket代码中循环这么慢

rns*_*nso 5 scheme loops for-loop racket

我试图找到最小的非除数数(https://codegolf.stackexchange.com/questions/105412/find-the-smallest-number-that-doesnt-divide-n).以下版本使用'named let'正常工作:

(define (f1 m)
  (let loop ((n 2))
    (cond
      [(= 0 (modulo m n))
       (loop (+ 1 n))]
      [else n])))
Run Code Online (Sandbox Code Playgroud)

我正在测试:

(f 24)
(f 1234567)
(f 12252240)
(f 232792560)
Run Code Online (Sandbox Code Playgroud)

以上版本产生以下输出:5 2 19和23.

但是,使用内置for循环的以下版本非常慢,实际上会因内存不足而出现错误并且数字较大:

(define (f2 m)
  (for/first ((i (range 2 m))
              #:when (not (= 0 (modulo m i)))
              #:final (not (= 0 (modulo m i))))
    i))
Run Code Online (Sandbox Code Playgroud)

for与Racket中的命名let相比,第二版的代码是否存在错误或循环效率低?

Rya*_*per 6

range函数实际上分配了一个列表,因此您的函数的时间由巨大的列表分配支配.in-range改为使用:

(define (f2 m)
  (for/first ([i (in-range 2 m)]
              #:when (not (= 0 (modulo m i)))
              #:final (not (= 0 (modulo m i))))
    i))
Run Code Online (Sandbox Code Playgroud)

有关不同序列形式的相对速度的更多说明,另请参阅"球拍指南"中的" for性能 "部分.