在列表方案中用 0 到 100 之间的随机数替换令牌 RANDOM

Replacing token RANDOM with a random number between 0 and 100 in a list scheme

背景

我在方案中有这个当前程序

(define (tsar subj srch repl)
   (cond
         ((list? subj)
          (map
              (lambda (lst) (tsar lst srch repl))
              subj))
         (else
              (if (equal? subj repl)
                   srch
                   subj))))

这个函数以一个主题subj作为参数(一般来说这应该是一个列表),一个要在列表中搜索的值srch和一个用来替换该值的值repl

现在一般情况下,这个功能有效:

例如:

(display(tsar '(1 2 () 4 (7 (7 (3 7)))) '() 3))

产量

(1 2 () 4 (7 (7 (() 7))))

列表中的原子 3 按预期替换为 ()

问题

我需要解决这个程序的另一个问题,在原子 RANDOM 包含在列表中的情况下,我们需要使用 [= 将原子替换为 0-100 之间的随机数19=].

我知道(或认为我知道)

我知道我可能应该使用 eq? 或类似的东西来确定原子是否是随机的。我也知道(也许)我可以通过将列表作为 subjRANDOM 作为 srch 和 [=19= 传递来递归地使用 tsar 函数来实现此目的] 作为 repl.

我正在努力思考如何实现这一点(我对一般的方案和函数式编程几乎完全陌生)

为澄清起见,RANDOM 不是字符串,它是一个符号

通常,您可以通过引用来测试该特定符号,然后 return (random 100) 的结果 - 假设 (random 100) return 的结果介于 0 和 100 之间在你的计划中,这显然不是标准的——否则又是这个主题:

(if (eq? subj 'random)
    (random 100)
    subj))

您可以将此 (eq?subj 'RANDOM) 作为子句放在函数的 COND 语句中:

(define (tsar subj srch repl)
   (cond
         ((list? subj)
          (map
              (lambda (lst) (tsar lst srch repl))
               subj))
         ((eq? subj 'random)
               (random 100))
         (else
              (if (equal? subj repl)
                   srch
                   subj))))

(删除了无关的 'if' 条件。)

顺便说一句:至少我测试的方案 BiwaScheme 具有特定于大写字母的符号,因此 'random、'Random、'RANDOM 等都相互测试为假,您需要一个 COND每个符号的子句。我不确定如何将它们组合到一般情况下。

我怀疑你有 srchrepl 倒退:你真的想用 srch 替换 repl 吗?您还以非惯用方式使用 cond:您不需要写

(cond
  ...
  (else (if x y z)))

因为cond的主体本身就是一堆条件和结果,所以你可以把它变成

(cond
  ...
  (x y)
  (else z))

所以这是你的函数,改变了这些东西(这是 Racket,你可能需要将 [...] 更改为 (...) 并将 λ 更改为 lambda):

(define (tsar subj srch repl)
   (cond
     [(list? subj)
      (map (λ (lst) (tsar lst srch repl)) subj)]
     [(equal? subj srch)
      repl]
     [else subj]))

现在,确定修复此问题以检查 RANDOM 我们需要 cond 中的另一个子句来检查 RANDOM。我不打算写它,但它的测试将是 (eqv? subj 'RANDOM),结果可能是 (random 100).

使用 mit-scheme 进行了测试:

1 ]=> (fold-right (lambda (x a) (if (eq? x 'random) (cons (random 100) a) (cons x a))) '() '(1 2 3))

;Value: (1 2 3)

1 ]=> (fold-right (lambda (x a) (if (eq? x 'random) (cons (random 100) a) (cons x a))) '() '(1 random 3))

;Value: (1 38 3)

1 ]=> (fold-right (lambda (x a) (if (eq? x 'random) (cons (random 100) a) (cons x a))) '() '(1 random random))

;Value: (1 97 50)

所以你可以这样做:

(define (doit input)
  (fold-right
    (lambda (x a)
      (if (eq? x 'random)
          (cons (random 100) a)
          (cons x a)))
    '()
    input)