首先,用缩进来表达嵌套结构是一种很好的风格,所以视觉上很明显;并且还要将if
's 的每个子句,即consequent和 the alternative,放在它自己的行上:
(define (isPrimeHelper x k)
(if (= x k)
#t ; consequent
(if (= (remainder x k) 0) ; alternative
;; ^^ indentation
#f ; consequent
(isPrimeHelper x (+ k 1))))) ; alternative
(define (printPrimesUpTo n)
(define result '())
(define (helper x)
(if (= x (+ 1 n))
result ; consequent
(if (isPrime x) ; alternative
(cons x result) )) ; no alternative!
;; ^^ indentation
( helper (+ x 1)))
( helper 1 ))
现在可以清楚地看到,您的函数所做的最后一件事就是始终使用递增的值helper
调用自身。x
没有停止条件,即这是一个无限循环。
另一件事是,调用(cons x result)
不会result
以任何方式改变 ' 值。为此,您需要设置它,如下所示(set! result (cons x result))
:您还需要将此表达式放在一个begin
组中,因为它不是根据其值进行评估,而是根据其副作用进行评估:
(define (helper x)
(if (= x (+ 1 n))
result
(begin
(if (isPrime x)
(set! result (cons x result)) ) ; no alternative!
(helper (+ x 1)) )))
通常,显式使用set!
被认为是不好的风格。表达循环的一种标准方法是使用命名 let的尾递归代码,通常使用规范名称“ ”(但它可以是任何名称):loop
(define (primesUpTo n)
(let loop ((x n)
(result '()))
(cond
((<= x 1) result) ; return the result
((isPrime x)
(loop (- x 1) (cons x result))) ; alter the result being built
(else (loop (- x 1) result))))) ; go on with the same result
在存在尾调用优化的情况下,它实际上等同于以前的版本。