I'm reading sicp and am writing a program to find the first 3 prime numbers from 1,000. I'm using an altered version of Fermat's method (However the algorithm is irrelevant in this case as I only need to understand the error message). The whole set of code is:
(define (fz-prime number count)
(if (< count 4)
(if (= (fz-fermat-loop number 1) 0)
(fz-prime (+ number 1) count)
((display number) (fz-prime (+ number 1) (+ count 1))))))
(define (fz-fermat-loop number count)
count
(if (> count 5)
1
(if (= (fz-fermat-test number (fz-random number)) 0)
0
(fz-fermat-loop number (+ count 1)))))
(define (fz-fermat-test number count)
(if (= (modulo count number) (modulo (fz-exp-wrapper count number) number))
1
0))
(define (fz-random number)
(random (- number 2)))
(define (fz-exp-wrapper base power)
(fz-exp base power 1))
(define (fz-exp base power result)
(if (<= power 0) result
(fz-exp base (- power 1) (* result base))))
(fz-prime 1000 1)
Now everytime I run the code, it shows the following error:
100910131019. . application: not a procedure;
expected a procedure that can be applied to arguments
given: #<void>
arguments...:
The first 3 numbers are the first three prime numbers, but I don't get what the error message says.
The error message suggests that you're using Racket, but also that you've chosen a language level that disables useful error messages such as the one I get when I copy your program into buffer in the #lang racket language:
if: missing an "else" expression in: (if (< count 4) (if (= (fz-fermat-loop number 1) 0)
(fz-prime (+ number 1) count) ((display number) (fz-prime (+ number 1) (+ count 1)))))
Actually, I bet you're using Jens Axel Soegaard's excellent sicp
language, which is entirely the right choice for working through sicp.... but is unfortunately missing some useful error messages.
Specifically, in the language you're using, an if
can be missing an else
branch, and if the test fails, it silently evaluates to the special # value.
Oh! But wait! You have another problem... you write
((display number) (fz-prime (+ number 1) (+ count 1)))
I bet you're thinking that if you just take two expressions such as (display number)
and (fz-prime ...)
and wrap them in parens, this means "do the first, then do the second." Actually, though, this means "the first expression evaluates to a function; call it with the arguments that result from evaluating the remaining expressions" and #void
is exactly what (display ...)
returns.
You might be looking for begin
, here, like so:
(begin
(display number)
(fz-prime (+ number 1) (+ count 1)))