0

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.

Will Ness
  • 70,110
  • 9
  • 98
  • 181
Nicholas Humphrey
  • 1,220
  • 1
  • 16
  • 33
  • 1
    Since John mentions several problems I won't mark as duplicate, but the error message is related to [My code signals the error “application: not a procedure” or “call to non procedure”](https://stackoverflow.com/q/48064955/1565698) and specifically "Trying to group expressions or create a block" in the answer. – Sylwester May 04 '18 at 11:44

1 Answers1

2

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)))
Will Ness
  • 70,110
  • 9
  • 98
  • 181
John Clements
  • 16,895
  • 3
  • 37
  • 52
  • Thanks! Actually I'm using scheme and there is a #lang sicp before the code, but somehow stackoverflow does not parse it well so I removed it but forgot to mention it. Is there a way to increase the output of error messages in DrRacket? I also don't get it why I need an else for an if in Scheme. BTW I just added an else and it complains that else not allowed as an expression. – Nicholas Humphrey May 04 '18 at 03:34
  • BTW would appreciate if you can share a link about the conditional structure in Scheme. I taught myself C++ and conditional and loop only take about an hour to learn, but not so for Scheme. SICP does not give much detail and Racket doc doesn't give much either. I have been writing Scheme for more than a week and still I don't get if. And AFAIK Scheme does not have loop... – Nicholas Humphrey May 04 '18 at 03:37
  • The best reference here is How to Design Programs, a (free online) textbook (https://www.htdp.org) that's written by many of the authors of DrRacket. In fact, Scheme *does* have loops, and also most of the imperative features that you find in other programming languages, but Scheme is generally organized you to steer you toward functional solutions. One great example is associated with your earlier question: why do you have to have an else? The answer comes from math: if you don't have an else, what is the function supposed to return? Rather than thinking about what functions *do*... – John Clements May 04 '18 at 03:41
  • you think about what they *return*. – John Clements May 04 '18 at 03:41
  • Ah thanks, "begin" seems to be the right one here! The reason I use brackets is that I was not sure how to run more than one statements for a branch. The reason I excluded "else" is that from previous experience Scheme seems to be quite tolerate when there is no "else", but of course I could be wrong. Thanks again, already accepted! – Nicholas Humphrey May 04 '18 at 03:44
  • Just a couple more questions. I heard about HTDP, and people said it is an easier alternative for SICP. Do you think it's useful to read that before SICP? And what about the Little Schemer? Thanks. Anyway I'll continue to read SICP and check grammar here and there. – Nicholas Humphrey May 04 '18 at 03:46
  • 1
    @NicholasHumphrey for a faster-paced text check out http://ds26gte.github.io/tyscheme/ or https://www.scheme.com/tspl4/. – Will Ness May 04 '18 at 11:38
  • @WillNess Thanks! Will check it out – Nicholas Humphrey May 04 '18 at 12:39