有没有办法使用 if 语句而不是 cond 来编写这个函数?以下按预期工作,但我很想看到另一种选择。
(define (harmonic-numbers n)
(cond ((= n 1) 1)
((> n 1) (+ (/ 1 n)
(harmonic-numbers(- n 1))))))
当然,acond
可以实现为一系列嵌套if
的 s。请注意,您的代码中存在潜在错误,如果n
小于会发生什么1
?
(define (harmonic-numbers n)
(if (= n 1)
1
(if (> n 1)
(+ (/ 1 n) (harmonic-numbers (- n 1)))
(error 'undefined))))
根据使用的 Scheme 解释器,表单可能要求您始终为所有条件提供“else”部分(这就是为什么我在小于if
时发出错误信号的原因)。其他解释器没有那么严格,很乐意让你写一个单臂条件:n
1
(define (harmonic-numbers n)
(if (= n 1)
1
(if (> n 1)
(+ (/ 1 n) (harmonic-numbers (- n 1))))))
编辑
现在我们已经确定了如果n
小于 1 会发生什么,我们可以使用以下代码编写一个更简单的版本if
:
(define (harmonic-numbers n)
(if (<= n 1)
1
(+ (/ 1 n) (harmonic-numbers (- n 1)))))
这是使用的等效版本cond
:
(define (harmonic-numbers n)
(cond ((<= n 1) 1)
(else (+ (/ 1 n) (harmonic-numbers (- n 1))))))
cond
在 R6RS 规范中被称为Derived 条件并且不是必要的语法,就像if
is。它不需要作为原语,但可以定义为宏。这是 R5RS 规范中定义的 cond 的定义,但它与使用 syntax-case 宏定义的current 兼容:
(define-syntax cond
(syntax-rules (else =>)
((cond (else result1 result2 ...))
(begin result1 result2 ...))
((cond (test => result))
(let ((temp test))
(if temp (result temp))))
((cond (test => result) clause1 clause2 ...)
(let ((temp test))
(if temp
(result temp)
(cond clause1 clause2 ...))))
((cond (test)) test)
((cond (test) clause1 clause2 ...)
(let ((temp test))
(if temp
temp
(cond clause1 clause2 ...))))
((cond (test result1 result2 ...))
(if test (begin result1 result2 ...)))
((cond (test result1 result2 ...)
clause1 clause2 ...)
(if test
(begin result1 result2 ...)
(cond clause1 clause2 ...)))))