this is possibly much of an elementary question, but I'm having trouble with a procedure I have to write in Scheme. The procedure should return all the prime numbers less or equal to N (N is from input).
(define (isPrimeHelper x k)
(if (= x k) #t
(if (= (remainder x k) 0) #f
(isPrimeHelper x (+ k 1)))))
(define ( isPrime x )
(cond
(( = x 1 ) #t)
(( = x 2 ) #t)
( else (isPrimeHelper x 2 ) )))
(define (printPrimesUpTo n)
(define result '())
(define (helper x)
(if (= x (+ 1 n)) result
(if (isPrime x) (cons x result) ))
( helper (+ x 1)))
( helper 1 ))
My check for prime works, however the function printPrimesUpTo
seem to loop forever. Basically the idea is to check whether a number is prime and put it in a result list.
Thanks :)
You can do this much more nicely. I reformated your code:
Please don’t write Scheme like C or Java – and have a look at these style rules for languages of the lisp-family for the sake of readability: Do not use camel-case, do not put parentheses on own lines, mark predicates with
?
, take care of correct indentation, do not put additional whitespace within parentheses.The
(if)
expression in your(helper)
function is not the tail expression of the function, and so is not returned, but control will always continue to(helper (+ x 1))
and recurse.The more efficient
prime?
(from Sedgewick's "Algorithms"):You have several things wrong, and your code is very non-idiomatic. First, the number 1 is not prime; in fact, is it neither prime nor composite. Second, the
result
variable isn't doing what you think it is. Third, your use ofif
is incorrect everywhere it appears;if
is an expression, not a statement as in some other programming languages. And, as a matter of style, closing parentheses are stacked at the end of the line, and don't occupy a line of their own. You need to talk with your professor or teaching assistant to clear up some basic misconceptions about Scheme.The best algorithm to find the primes less than n is the Sieve of Eratosthenes, invented about twenty-two centuries ago by a Greek mathematician who invented the leap day and a system of latitude and longitude, accurately measured the circumference of the Earth and the distance from Earth to Sun, and was chief librarian of Ptolemy's library at Alexandria. Here is a simple version of his algorithm:
Called as
(primes 50)
, that returns the list(2 3 5 7 11 13 17 19 23 29 31 37 41 43 47)
. It is much faster than testing numbers for primality by trial division, as you are attempting to do. If you must, here is a proper primality checker:Improvements are possible for both algorithms. If you are interested, I modestly recommend this essay on my blog.
First, it is good style to express nested structure by indentation, so it is visually apparent; and also to put each of
if
's clauses, the consequent and the alternative, on its own line:Now it is plainly seen that the last thing that your
helper
function does is to call itself with an incrementedx
value, always. There's no stopping conditions, i.e. this is an infinite loop.Another thing is, calling
(cons x result)
does not alterresult
's value in any way. For that, you need to set it, like so:(set! result (cons x result))
. You also need to put this expression in abegin
group, as it is evaluated not for its value, but for its side-effect:Usually, the explicit use of
set!
is considered bad style. One standard way to express loops is as tail-recursive code using named let, usually with the canonical name "loop
" (but it can be any name whatever):which, in presence of tail-call optimization, is actually equivalent to the previous version.