我正在尝试编写一个通过iteratve进程计算f的过程。函数f由
规则定义f(n)= n,如果n < 4和
f(n)= f(n - 1)+ 2f(n - 2)+ 3f(n - 3)+ 4f(n - 4),如果n> = 4。
这是我的程序:
(define (f n)
(define (newF temp n)
(letrec ((first (- n 1))
(second (- n 2))
(third/fourth (- n 3))
(fifth (- n 4)))
(define (d)
((if (< first 4) (set! temp (+ temp first)) (newF temp first))
(if (< second 4) (set! temp (+ temp (* second 2))) (newF temp second))
(if (< third/fourth 4) (set! temp (+ temp (* third/fourth 3) (* third/fourth 4))) (newF temp third/fourth))
(if (< fifth 4) (set! temp (+ temp (* fifth 4)))(newF temp fifth))))
(d))
temp)
(newF 0 n))
不幸的是,当我跑(f 7)时,我收到了这个错误(引用了if语句体):
application: not a procedure;
expected a procedure that can be applied to arguments
given: #<void>
arguments...:
#<void>
#<void>
#<void>
任何人都知道我为什么以及如何解决它的原因?
答案 0 :(得分:3)
根据your previous question,你以完全必要的方式处理它(当然不正确,否则你不会问这个问题),这不是Scheme喜欢的方式上班。这是编写函数的函数(但不是迭代)方法:
(define (f n)
(if (< n 4)
n
(+ (f (- n 1)) (* 2 (f (- n 2))) (* 3 (f (- n 3))) (* 4 (f (- n 4))))))
现在,让我们看看如何迭代地写这个。首先,让我们看看如何编写迭代的Fibonacci函数:
(define (fib n)
(let loop ((i 0) (a 0) (b 1))
(if (>= i n)
a
(loop (+ i 1) b (+ a b)))))
这与以下JavaScript的作用相同:
fib = function (n) {
return (function loop(i, a, b) {
return i >= n ? a : loop(i + 1, b, a + b);
})(0, 0, 1);
};
请注意i
,a
和b
实际上如何更新。我们使用尾递归来更新值,而不是通过重新分配/变异(即,不使用JS中的=
或Scheme中的set!
)。我最近写了一篇关于why tail-recursion is so important in Scheme的答案。
所以,你会做一些与你的功能类似的东西:
(define (f n)
(let loop ((i 0) (a 0) (b 1) (c 2) (d 3))
(if (>= i n)
a
(loop (+ i 1) b c d (+ d c c b b b a a a a)))))
答案 1 :(得分:2)
报告错误是因为()
帮助程序中的表达式存在一些不必要的d
。你不必这样做,程序中的所有表达都隐含在begin
内,没有必要使用()
表示他们全部代码块的一部分 - 此外,当我们用()
包围表达式时,解释器会尝试将表达式应用为一个过程 - 因此application: not a procedure
错误。
除此之外,还有一些关于风格的评论。在Scheme中,我们尽量避免使用set!
,这不是解决此编程语言中的问题的惯用方法。此外,您还在覆盖Racket中的一些内置程序:first
,second
和fifth
是已在使用的名称,您不应将它们用于您自己的变量。