Reputation: 69
This the task:
Write a function (random-number-list n lim) which returns a list of n random integers in the range 0 through lim-1
This is my Code: (I am using #lang EOPL in DrRacket)
(define (random-number-list n lim)
(letrec ((maker
(lambda (n lim result)
(let loop ((g lim) (result '()))
(if (= g 0)
result
(loop (- lim 1) (cons (random lim) result)))))))
(maker n lim '())))
This should be what it produce:
(random-number-list 10 20) => (1 11 4 18 3 12 17 17 8 4)
When I run the code I receive an error dealing with "(random lim)." Something to with random. Would anyone know the reason? Also, am I on the correct track?
Upvotes: 2
Views: 933
Reputation: 31145
An alternative:
(define (random-number-list n lim)
(build-list n (λ (x) (random lim)))
Here build-list
builds a list of n
elements.
Each element is the result of calling (λ (x) (random lim))
which ignores x
and returns a random number between 0 and lim-1
.
Upvotes: 0
Reputation: 48775
The main reason you get an error is that the langiage #!eopl
doesn have a procedure named random
. If you se the eported symbols of eopl it simply doesn't exist. It does exist in #!racket
though.
As Oscar pointed out there were some logical errors that leads to infinite loops. An honest mistake, but I also notice you use g
instead of n
in your inner loop. It's very common to use the original name instead of the chosen local variable so a common way to not do that mistake is to shadow the original variable.
There is also only need for one local procedure. Here are my corrections with either keeping the named let
or the letrec
:
#!racket
;; with letrec
(define (random-number-list n lim)
(letrec ((maker
(lambda (n result)
(if (zero? n)
result
(maker (- n 1)
(cons (random lim) result))))))
(maker n '())))
;; with named let
(define (random-number-list2 n lim)
(let maker ((n n) (result '()))
(if (zero? n)
result
(maker (- n 1)
(cons (random lim) result)))))
I left lim
out since it never changes and i used the same name maker
to illustrate it's exactly the same that happens in these two, only the syntax are different. Many implementations actually rewrites the named let
to something very similar to the letrec
version.
Upvotes: 2
Reputation: 236140
The main problem with your code is in this line:
(loop (- lim 1) (cons (random lim) result))
You're decrementing lim
but testing against g
, which remains unchanged, leading to an infinite loop. Also, g
was incorrectly initialized in this line:
((g lim) (result '()))
This should fix the problems:
(define (random-number-list n lim)
(letrec ((maker
(lambda (n lim result)
(let loop ((g n) (result '()))
(if (= g 0)
result
(loop (- g 1) (cons (random lim) result)))))))
(maker n lim '())))
Given that you're using Racket, know that a simpler solution is possible:
(define (random-number-list n lim)
(build-list n (lambda (x) (random lim))))
Either way, it works as expected:
(random-number-list 10 20)
=> '(13 7 5 9 3 12 7 8 0 4)
Upvotes: 2