【发布时间】:2013-09-13 11:08:00
【问题描述】:
有没有办法使用 if 语句而不是 cond 来编写这个函数?以下内容按预期工作,但我很想看到另一个选项。
(define (harmonic-numbers n)
(cond ((= n 1) 1)
((> n 1) (+ (/ 1 n)
(harmonic-numbers(- n 1))))))
【问题讨论】:
有没有办法使用 if 语句而不是 cond 来编写这个函数?以下内容按预期工作,但我很想看到另一个选项。
(define (harmonic-numbers n)
(cond ((= n 1) 1)
((> n 1) (+ (/ 1 n)
(harmonic-numbers(- n 1))))))
【问题讨论】:
当然,cond 可以实现为一系列嵌套的ifs。请注意,您的代码中有一个潜在的错误,如果 n 小于 1 会发生什么?
(define (harmonic-numbers n)
(if (= n 1)
1
(if (> n 1)
(+ (/ 1 n) (harmonic-numbers (- n 1)))
(error 'undefined))))
根据使用的 Scheme 解释器,if 表单可能要求您始终为所有条件提供“else”部分(这就是为什么我在 n 小于 1 时发出错误信号的原因)。其他口译员没有那么严格,很乐意让你写一个单臂条件:
(define (harmonic-numbers n)
(if (= n 1)
1
(if (> n 1)
(+ (/ 1 n) (harmonic-numbers (- n 1))))))
编辑
现在我们已经确定了如果n 小于一会发生什么,我们可以使用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))))))
【讨论】:
#<void>,如果 n 小于 1,则返回 false 或 undefined(取决于解释器)。仔细看我回答的最后一部分,一旦我们意识到条件是互斥的,就可以简化函数——非常适合使用if
cond 在 R6RS 规范中被称为 Derived conditional 并且不是基本语法,就像 if 一样。它不需要作为原语,但可以定义为宏。这是 R5RS 规范中定义的 cond 的定义,但它与 defined with syntax-case macros 的电流兼容:
(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 ...)))))
【讨论】: