以下是对 1/2^n 求和直到达到 0 的函数。有人可以告诉我是否需要 else 语句,以及如何安排括号以防止编译错误?
(define (zeno n)
(if (= n 0)
(+ 0)
(else
((+ (/ 1 (expt 2 n )))
((zeno(- n 1)))))))
以下是对 1/2^n 求和直到达到 0 的函数。有人可以告诉我是否需要 else 语句,以及如何安排括号以防止编译错误?
(define (zeno n)
(if (= n 0)
(+ 0)
(else
((+ (/ 1 (expt 2 n )))
((zeno(- n 1)))))))
我有我的帽子,我的茶,在工作中有一段时间无事可做。你知道现在几点了。
[dons code-review hat]
首先,如果您正确缩进了您的代码,它将显示为
(define (zeno n)
(if (= n 0)
(+ 0)
(else
((+ (/ 1 (expt 2 n)))
((zeno (- n 1)))))))
if
在Scheme中不像if
//类C 语言的构造。它实际上是三元运算符。换句话说,在这种情况下没有任何意义。then
else
else
(define (zeno n)
(if (= n 0)
(+ 0)
((+ (/ 1 (expt 2 n)))
((zeno (- n 1)))))))
你不需要使用+
来返回一个数字;数字是自我评估的。
(define (zeno n)
(if (= n 0)
0
((+ (/ 1 (expt 2 n)))
((zeno (- n 1)))))))
当你有一个像这样的表达时(foo bar baz)
,它通常意味着
“调用
foo
带有参数的函数bar
和baz
”
您不能随意添加额外的括号;那些改变了表达的意思。例如,((foo) (bar baz))
意味着
“不带参数调用函数,并用带参数
foo
调用的结果调用其结果”bar
baz
换句话说,
...
((+ (/ 1 (expt 2 n)))
((zeno (- n 1))))))
你在说什么,几乎可以肯定不是这个意思,这里是
“使用不带参数的参数
(+ (/ 1 (expt 2 n)))
调用结果调用函数。”zeno
(- n 1)
你的意思似乎是
"用小于一的调用结果加上
1
除以"2^n
zeno
n
这意味着你应该说的是
(define (zeno n)
(if (= n 0)
0
(+ (/ 1 (expt 2 n))
(zeno (- n 1)))))
对于完全不同的方法,这使用显式do
循环来进行求和。它避免使用expt
(按设计)。
(define (zeno n)
(do ((n n (- n 1))
(sum 0 (+ sum frac))
(frac 1/2 (/ frac 2)))
((zero? n) sum)))
当写成等效的命名let
形式时,它可能更具可读性,也可能不更具可读性:
(define (zeno n)
(let loop ((n n)
(sum 0)
(frac 1/2))
(if (zero? n)
sum
(loop (- n 1) (+ sum frac) (/ frac 2)))))
对于更完全不同的方法,您可以使用SRFI 41流:
(define zeno
(let ((frac-stream (stream-iterate (cut / <> 2) 1/2)))
(lambda (n)
(stream-fold + 0 (stream-take n frac-stream)))))
(除了 SRFI 41 之外,上面的代码片段还需要加载SRFI 26。)
甚至更完全不同的方法:只需使用封闭形式的解决方案!(谢谢,WorBlux。)
(define (zeno n)
(- 1 (/ (expt 2 n))))
您有几个语法错误(主要是错误的括号),并且if
表单没有使用else
- 不要误会我的意思,它确实有一个“else”部分,只是您不能明确地写else
它才能工作. 我相信这就是您的目标:
(define (zeno n)
(if (= n 0)
0
(+ (/ 1 (expt 2 n))
(zeno (- n 1)))))