首页 > 解决方案 > 在 Scheme 中分配变量而不使用 set

问题描述

我正在尝试在我的方案程序中创建一个全局分数,对于我的函数的每次迭代,它要么增加 1,减少 1,要么不改变。例如,当我希望分数增加 1 时,我的函数中有这个:

(set! score (+ score 1)))

我可以使用 set 来做到这一点!但我需要一种不使用集合的方法来实现它!手术。任何帮助,将不胜感激!

标签: schemelispracketr5rs

解决方案


诀窍是要意识到你可以替换这样的东西:

(define (my-game ...)
  (let ([score 0])
    (some-kind-of-looping-construct
     ...
     (if <not-done>
         (begin
           (set! score <new-score-value>)
           (continue-loop))
         score))))

像这样:

(define (my-game ...)
  (define (loop ... score ...)
    ...
    (if <not-done>
        (loop ... <new-score-value> ...)
        score))
  (loop ... 0 ...))

特别是,您可以通过对重复绑定变量的某个函数的文本(但不是实际上)递归调用来替换任何重复分配给某个变量的循环构造。

具体来说,让我们假设我们有一个循环结构,看起来像

(loop exit-fn form ...)

loop循环结构也是如此,exit-fn也是我们用来退出循环的神奇事物。

我假设有一些函数run-game-round需要一个整数和当前分数,运行一轮游戏并返回新分数。

所以使用这个结构,我们可以编写某种游戏循环的骨架:

(let ((round 0)
      (score 0))
  (loop exit
    (set! score (run-game-round round score))
    (set! round (+ round 1))
    (cond
      [(> score 100)
       (exit 'win)]
      [(> round 100)
       (exit 'lose)])))

这是相当可怕的代码。

但是我们可以用这个替换这段代码:

(begin
  (define (run-game round score)
    (cond [(> score 100)
           'win]
          [(> round 100)
           'lose]
          [else
           (run-game (+ round 1)
                     (run-game-round round score))]))
  (run-game 0 0))

这段代码做的事情完全相同,但在任何地方都没有赋值。


推荐阅读