在球拍中引用变量

时间:2015-12-20 11:55:10

标签: functional-programming scheme lisp racket

我正在尝试编写一个简单的程序来查找n:th prime但我不认为我理解如何在球拍中正确引用变量。

我想要的是内部程序 sieve-iter 将素数添加到列表 primlst 中,该列表位于 sieve 的命名空间中但是我得到一个无限循环。我的猜测是 sieve-iter 中的 primlst 会导致问题。

(define (sieve n) ;; returns the n:th prime (n>0) 
  (let [(primlst '(2))
        (cand 3)]
    (define (sieve-iter i lst)
      (cond ((null? lst) (and (cons i primlst) (sieve-iter (+ i 2) primlst))) ;;prime
            ((= (length primlst) n) (car primlst)) ;;end
            ((= (modulo i (car lst)) 0) (sieve-iter (+ i 2) primlst)) ;;non-prime
            (#t (sieve-iter n (cdr lst))))) ;;unclear if prime
  (sieve-iter cand primlst)))

任何帮助表示赞赏!

1 个答案:

答案 0 :(得分:0)

你试图在一个函数中做太多,让prime-iter只是担心迭代来建立素数列表。制作另一个内部函数来递减现有素数以测试新候选者。

(define (sieve n) ;; returns the n:th prime (n>0) 
  (define (sieve-iter i lst remaining)
    (cond ;((null? lst) (and (cons i primlst) (sieve-iter (+ i 2) primlst))) ;;should never be null, we are building the list up
            ((<= remaining 0) (car lst)) ;;checking length every time gets expensive added a variable to the function
            ((sieve-prime? i lst) ;;if prime add to lst and recurse on next i
             (sieve-iter (+ i 2) (cons i lst) (- remaining 1)))
            (else 
             (sieve-iter (+ i 2) lst remaining)))) ; else try next
  (define (sieve-prime? i lst)
    (cond ((null? lst) #t)
          ((= 0 (modulo i (car lst))) #f)
          (else (sieve-prime? i (cdr lst))))) 

    (let ((primlst '(2)) ;;you generally don't modify these, 
          (cand 3)) ;mostly they just bind values to name for convenience or keep from having to re-calculate the same thing more than once      
     (sieve-iter cand primlst (- n 1))))

你可以使用套装!修改之前的原始列表,但该过程显然不再是纯函数。

在调用筛子素数时,还有另一种低处理优化吗?过滤lst参数以删除大于i的平方根的值。