在本页中:
4.9.1 赋值使用准则
4.9.2 多重赋值:set!-values

4.9 赋值:set!

+The Racket ReferenceAssignment: set! and set!-values一节中也提供了set!的文档。

对变量赋值使用 set!

(set! id expr)

set! 表达式对 expr 进行求值并更改 id (它必须在环境内被绑定)的值为该结果。set! 表达式的结果本身为 #<void>

例如:
(define greeted null)
(define (greet name)
  (set! greeted (cons name greeted))
  (string-append "Hello, " name))
> (greet "Athos")

"Hello, Athos"

> (greet "Porthos")

"Hello, Porthos"

> (greet "Aramis")

"Hello, Aramis"

> greeted

'("Aramis" "Porthos" "Athos")

(define (make-running-total)
  (let ([n 0])
    (lambda ()
      (set! n (+ n 1))
      n)))
(define win (make-running-total))
(define lose (make-running-total))

 

> (win)

1

> (win)

2

> (lose)

1

> (win)

3

4.9.1 赋值使用准则

尽管有时使用 set! 是恰当的,但 Racket 的风格通常不鼓励使用 set!。以下准则可以帮助你澄清何时使用 set! 是恰当的。

其它所有等价的情况下,不使用赋值或可变量的程序总是优于使用赋值或可变量的程序。 然而,即便在副作用可以被避免的情况下,当使用赋值能够显著提升可读性或能够实现 明显更好的算法时,那就应该使用它。

比起直接使用 set! 来说,使用向量或散列表这类可变值能减少 对程序风格的疑虑,然而,简单地将程序中的 set! 替换为 vector-set! 显然无法提升程序的风格。

4.9.2 多重赋值:set!-values

+The Racket ReferenceAssignment: set! and set!-values一节中也提供了set!-values的文档。

set!-values 形式可一次对多个变量赋值,给定一个产生对应数量的值的表达式:

(set!-values (id ...) expr)

此形式等价于使用 let-valuesexpr 中接收多个结果, 然后使用 set! 将这些结果分别赋予这些 id

例如:
(define game
  (let ([w 0]
        [l 0])
    (lambda (win?)
      (if win?
          (set! w (+ w 1))
          (set! l (+ l 1)))
      (begin0
        (values w l)
        ; 交换位置...
        (set!-values (w l) (values l w))))))
> (game #t)

1

0

> (game #t)

1

1

> (game #f)

1

2