set!
在方案中使用赋值运算符有什么意义?为什么不只是rebind
使用变量到新值define
?
> (define x 100) > (define (value-of-x) x) ;; value-of-x closes over "x" > x 100 > (value-of-x) 100 > (set! x (+ x 1)) > x 101 > (value-of-x) 101 > (define x (+ x 1)) > x 102 > (value-of-x) 102 >
Kyle Cronin.. 39
虽然双方define
并set!
当在同一范围内,他们做两个不同的东西时,范围不同将重新定义的值.这是一个例子:
(define x 3) (define (foo) (define x 4) x) (define (bar) (set! x 4) x) (foo) ; returns 4 x ; still 3 (bar) ; returns 4 x ; is now 4
如您所见,当我们创建一个新的词法范围(例如当我们define
是一个函数)时,该范围内定义的任何名称都会掩盖显示在封闭范围内的名称.这意味着,当我们define
ð x
到4
在foo
,我们确实创造了一个新的值x
是阴影的旧值.在bar
,由于foo
在该范围内不存在,set!
查看封闭范围以查找和更改其值x
.
此外,正如其他人所说,你只应该define
在范围内使用一次名字.一些实现将让你逃脱多个define
s,而有些则不会.此外,您只应该使用set!
已经存在的变量define
.同样,强制执行此规则的严格程度取决于实施.
虽然双方define
并set!
当在同一范围内,他们做两个不同的东西时,范围不同将重新定义的值.这是一个例子:
(define x 3) (define (foo) (define x 4) x) (define (bar) (set! x 4) x) (foo) ; returns 4 x ; still 3 (bar) ; returns 4 x ; is now 4
如您所见,当我们创建一个新的词法范围(例如当我们define
是一个函数)时,该范围内定义的任何名称都会掩盖显示在封闭范围内的名称.这意味着,当我们define
ð x
到4
在foo
,我们确实创造了一个新的值x
是阴影的旧值.在bar
,由于foo
在该范围内不存在,set!
查看封闭范围以查找和更改其值x
.
此外,正如其他人所说,你只应该define
在范围内使用一次名字.一些实现将让你逃脱多个define
s,而有些则不会.此外,您只应该使用set!
已经存在的变量define
.同样,强制执行此规则的严格程度取决于实施.
通常不允许define
变量多于一次.当你尝试解决问题时,大多数REPL允许它方便,但如果你试图在Scheme程序中这样做,它会给你一个错误.
例如,在mzscheme中,该程序
#lang scheme (define x 1) (define x 2)
给出了错误
test.ss:3:8: module: duplicate definition for identifier at: x in: (define-values (x) 2)
另外,define
在其他上下文中使用时具有不同的含义.该程序
#lang scheme (define x 1) x (let () (define x 2) x) x
有输出
1 2 1
这是因为define
某些结构中的letrec
s 实际上被视为s.