EOPL/Racket/Scheme 两个数字之间的随机数列表
EOPL/Racket/Scheme Random Number List between two numbers
这个任务:
写一个函数 (random-number-list n lim) returns n 个随机整数的列表,范围从 0 到 lim-1
这是我的代码:(我在 DrRacket 中使用#lang EOPL)
(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 '())))
这应该是它产生的结果:
(random-number-list 10 20) => (1 11 4 18 3 12 17 17 8 4)
当我 运行 代码时,我收到处理“(random lim)”的错误。随机的东西。有人知道原因吗?另外,我走的路对吗?
您的代码的主要问题在于这一行:
(loop (- lim 1) (cons (random lim) result))
您正在递减 lim
,但针对 g
进行测试,它保持不变,从而导致无限循环。此外,g
在此行中被错误地初始化:
((g lim) (result '()))
这应该可以解决问题:
(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 '())))
鉴于您使用的是 Racket,请知道可能有更简单的解决方案:
(define (random-number-list n lim)
(build-list n (lambda (x) (random lim))))
无论哪种方式,它都按预期工作:
(random-number-list 10 20)
=> '(13 7 5 9 3 12 7 8 0 4)
出现错误的主要原因是语言 #!eopl
没有名为 random
的过程。如果您看到 eported symbols of eopl it 根本不存在。不过它确实存在于 #!racket
中。
正如 Oscar 所指出的,存在一些导致无限循环的逻辑错误。一个诚实的错误,但我也注意到你在你的内部循环中使用 g
而不是 n
。使用 原始名称 而不是选择的局部变量是很常见的,因此不犯该错误的常见方法是隐藏原始变量。
也只需要一个本地程序。这是我的更正,保留命名的 let
或 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)))))
我把 lim
留在外面,因为它永远不会改变,我使用相同的名称 maker
来说明这两者完全相同,只是语法不同。许多实现实际上将命名的 let
重写为与 letrec
版本非常相似的东西。
备选方案:
(define (random-number-list n lim)
(build-list n (λ (x) (random lim)))
此处 build-list
构建了一个包含 n
个元素的列表。
每个元素都是调用 (λ (x) (random lim))
的结果
忽略 x
和 returns 0 和 lim-1
之间的随机数。
这个任务:
写一个函数 (random-number-list n lim) returns n 个随机整数的列表,范围从 0 到 lim-1
这是我的代码:(我在 DrRacket 中使用#lang EOPL)
(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 '())))
这应该是它产生的结果:
(random-number-list 10 20) => (1 11 4 18 3 12 17 17 8 4)
当我 运行 代码时,我收到处理“(random lim)”的错误。随机的东西。有人知道原因吗?另外,我走的路对吗?
您的代码的主要问题在于这一行:
(loop (- lim 1) (cons (random lim) result))
您正在递减 lim
,但针对 g
进行测试,它保持不变,从而导致无限循环。此外,g
在此行中被错误地初始化:
((g lim) (result '()))
这应该可以解决问题:
(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 '())))
鉴于您使用的是 Racket,请知道可能有更简单的解决方案:
(define (random-number-list n lim)
(build-list n (lambda (x) (random lim))))
无论哪种方式,它都按预期工作:
(random-number-list 10 20)
=> '(13 7 5 9 3 12 7 8 0 4)
出现错误的主要原因是语言 #!eopl
没有名为 random
的过程。如果您看到 eported symbols of eopl it 根本不存在。不过它确实存在于 #!racket
中。
正如 Oscar 所指出的,存在一些导致无限循环的逻辑错误。一个诚实的错误,但我也注意到你在你的内部循环中使用 g
而不是 n
。使用 原始名称 而不是选择的局部变量是很常见的,因此不犯该错误的常见方法是隐藏原始变量。
也只需要一个本地程序。这是我的更正,保留命名的 let
或 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)))))
我把 lim
留在外面,因为它永远不会改变,我使用相同的名称 maker
来说明这两者完全相同,只是语法不同。许多实现实际上将命名的 let
重写为与 letrec
版本非常相似的东西。
备选方案:
(define (random-number-list n lim)
(build-list n (λ (x) (random lim)))
此处 build-list
构建了一个包含 n
个元素的列表。
每个元素都是调用 (λ (x) (random lim))
的结果
忽略 x
和 returns 0 和 lim-1
之间的随机数。