问题
I am trying to write a procedure that computes f by means of an iteratve process. The function f is defined by the rule that
f(n) = n, if n < 4 and
f(n) = f(n - 1) + 2f(n - 2) + 3f(n - 3) + 4f(n - 4), if n >= 4.
Here is my procedure:
(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))
Unfortunately, when I ran (f 7), I got this error(which referred to the if statement body):
application: not a procedure;
expected a procedure that can be applied to arguments
given: #<void>
arguments...:
#<void>
#<void>
#<void>
Anyone know the reason why and how I can fix it?
回答1:
Based on your previous question, you're going about it in a totally imperative way (and incorrect, of course, otherwise you wouldn't be asking this question), which is not how Scheme likes to work. Here's a functional (but not iterative) way to write the function:
(define (f n)
(if (< n 4)
n
(+ (f (- n 1)) (* 2 (f (- n 2))) (* 3 (f (- n 3))) (* 4 (f (- n 4))))))
Now, let's see how one might write this iteratively. First, let's see how an iterative Fibonacci function is written:
(define (fib n)
(let loop ((i 0) (a 0) (b 1))
(if (>= i n)
a
(loop (+ i 1) b (+ a b)))))
This does the same thing as the following JavaScript:
fib = function (n) {
return (function loop(i, a, b) {
return i >= n ? a : loop(i + 1, b, a + b);
})(0, 0, 1);
};
Notice how i
, a
, and b
actually get updated. We use tail-recursion to update the values, not by reassignment/mutation (i.e., not using =
in JS or set!
in Scheme). I recently wrote an answer about why tail-recursion is so important in Scheme.
So, you would do something similar with your function:
(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)))))
回答2:
The error reported occurs because there are a couple of unnecessary ()
surrounding the expressions inside the d
helper procedure. You don't have to do that, all the expressions inside a procedure are implicitly inside a begin
, there's no need to use ()
to indicate that they're all part of a block of code - and besides, when we surround an expression with ()
the interpreter tries to apply the expression as if it were a procedure - hence the application: not a procedure
error.
Other than that, some comments about style are in order. In Scheme, we try to avoid using set!
, that's not the idiomatic way to solve a problem in this programming language. Also, you're overwriting some built-in procedures in Racket: first
, second
and fifth
are names already in use, you should not use them for your own variables.
来源:https://stackoverflow.com/questions/26080321/why-am-i-getting-application-not-a-procedure