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 。使用 原始名称 而不是选择的局部变量是很常见的,因此不犯该错误的常见方法是隐藏原始变量。

也只需要一个本地程序。这是我的更正,保留命名的 letletrec:

#!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 之间的随机数。