-1

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?

C. K. Young
  • 219,335
  • 46
  • 382
  • 435
user3450695
  • 2,281
  • 4
  • 16
  • 16
  • 1
    You see the two `((` before the if? The `set!` returns void and it tries to apply that as a procedure – ಠ_ಠ Sep 28 '14 at 00:15
  • Did you search for that error message before asking this question? A [google search for `"application: not a procedure" site:stackoverflow.com`](https://www.google.com/search?q=%22application%3A+not+a+procedure%22+site%3Astackoverflow.com) turns up a whole bunch of results, and you'll quickly find that it's in the `((if ....) ...)`. That first `(if ...)` returns something (that's not a function), and then you try to call it like a function. – Joshua Taylor Sep 30 '14 at 12:00
  • possible duplicate of ["application: not a procedure" in binary arithmetic procedures](http://stackoverflow.com/questions/19022704/application-not-a-procedure-in-binary-arithmetic-procedures) – Joshua Taylor Sep 30 '14 at 12:01

2 Answers2

3

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)))))
Community
  • 1
  • 1
C. K. Young
  • 219,335
  • 46
  • 382
  • 435
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.

Óscar López
  • 232,561
  • 37
  • 312
  • 386