set用法的区别!并定义

Difference between usage of set! and define

在下面的代码中:

(define x 14)
(display x)       ; x = 14

(set! x 13)
(display x)       ; x = 13

(define x 14)
(display x)       ; x = 14
  
(set! y 13)       ; SchemeError: y not found!
(display y)      

如果 define 可以用于 set! 可以用于的一切,那么我们的用例是有人想在 define 上使用 set! + 实际定义本身?

define 在名称和值(变量)之间创建新绑定,set! 改变现有绑定。这些不是相同的操作,尽管 Python 这样的语言会混淆操作。

特别像

(define x 1)
...
(define x 2)

是非法的:您只能创建一次变量。实现可能不会检查这一点,但这并不能使其合法。创建绑定后,如果要修改它,则需要使用 set!.

实现(包括 Racket)在这方面故意草率的一个特殊情况是当它们被交互使用时。通常,如果您正在与系统交互,您可能想说,例如:

> (define square (λ (x) (+ x x)))
... ooops, that's not right, is it?
... Better fix it using the command-line editing
> (define square (λ (x) (* x x)))

在这种情况下,只允许重复定义事物显然对实施更好,因为这将使用户的生活变得更加轻松。

但是在程序中,在同一范围内重复定义(几乎?)总是错误,并且确实应该捕获它们:如果你想改变绑定,使用set!。尤其是 Racket 肯定会呕吐。


最后请注意 define 在所有地方都不合法 set! 是:即使在 Racket 中(它允许 define 在比 Scheme 更多的地方)这不是偶略合法代码:

(define (foo x)
  (define v x)
  (if (odd? x)
      (define v (* v 2))
      (define v (/ v 2)))
  v)

虽然这是

(define (foo x)
  (define v x)
  (if (odd? x)
      (set! v (* v 2))
      (set! v (/ v 2)))
  v)

(这仍然是糟糕的代码,但它是合法的。)。