我正在使用GCL在Ubuntu上编程.从各种来源的Common Lisp文档中,我了解到let创建局部变量,并setq设置现有变量的值.在下面的例子中,我需要创建两个变量并对它们的值求和.
setq(defun add_using_setq ()
(setq a 3) ; a never existed before , but still I'm able to assign value, what is its scope?
(setq b 4) ; b never existed before, but still I'm able to assign value, what is its scope?
(+ a b))
Run Code Online (Sandbox Code Playgroud)
let(defun add_using_let ( )
(let ((x 3) (y 4)) ; creating variables x and y
(+ x y)))
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,我似乎都取得了相同的结果; 使用setq和let这里有什么区别?为什么我不能setq在我需要使用的所有地方使用(因为它在语法上很容易)let?
Jos*_*lor 29
setq assigns a value to a variable, whereas let introduces new variables/bindings. E.g., look what happens in
(let ((x 3))
(print x) ; a
(let ((x 89))
(print x) ; b
(setq x 73)
(print x)) ; c
(print x)) ; d
3 ; a
89 ; b
73 ; c
3 ; d
Run Code Online (Sandbox Code Playgroud)
The outer let creates a local variable x, and the inner let creates another local variable shadowing the inner one. Notice that using let to shadow the variable doesn't affect the shadowed variable's value; the x in line d is the x introduced by the outer let, and its value hasn't changed. setq only affects the variable that it is called with. This example shows setq used with local variables, but it can also be with special variables (meaning, dynamically scoped, and usually defined with defparameter or defvar:
CL-USER> (defparameter *foo* 34)
*FOO*
CL-USER> (setq *foo* 93)
93
CL-USER> *foo*
93
Run Code Online (Sandbox Code Playgroud)
Note that setq doesn't (portably) create variables, whereas let, defvar, defparameter, &c. do. The behavior of setq when called with an argument that isn't a variable (yet) isn't defined, and it's up to an implementation to decide what to do. For instance, SBCL complains loudly:
CL-USER> (setq new-x 89)
; in: SETQ NEW-X
; (SETQ NEW-X 89)
;
; caught WARNING:
; undefined variable: NEW-X
;
; compilation unit finished
; Undefined variable:
; NEW-X
; caught 1 WARNING condition
89
Run Code Online (Sandbox Code Playgroud)
Of course, the best ways to get a better understanding of these concepts are to read and write more Lisp code (which comes with time) and to read the entries in the HyperSpec and follow the cross references, especially the glossary entries. E.g., the short descriptions from the HyperSpec for setq and let include:
Assigns values to variables.
let and let*create new variable bindings and execute a series of forms that use these bindings.
You may want to read more about variables and bindings. let and let* also have some special behavior with dynamic variables and special declarations (but you probably won't need to know about that for a while), and in certain cases (that you probably won't need to know about for a while) when a variable isn't actually a variable, setq is actually equivalent to setf. The HyperSpec has more details.
There are some not-quite duplicate questions on Stack Overflow that may, nonetheless, help in understanding the use of the various variable definition and assignment operators available in Common Lisp:
setq在未定义的变量上使用)小智 5
Let 几乎总是在函数定义内绑定变量的方式 - 除非在极少数情况下,您希望该值可用于同一范围内的其他函数。
\n我喜欢 emacs lisp 手册中的描述:
\n\n\nlet 用于将符号附加或绑定到值,这样 Lisp 解释器就不会将该变量与不属于函数的同名变量混淆。
\n要理解为什么需要 let 特殊形式,请考虑您拥有一个通常称为 \xe2\x80\x98the house,\xe2\x80\x99 的房屋的情况,如句子 \xe2\x80\x9cThe房子需要粉刷。\xe2\x80\x9d 如果你去拜访朋友,而你的主人指的是 \xe2\x80\x98 房子,\xe2\x80\x99 他可能指的是他的房子,而不是你的房子,即,到另一所房子。
\n如果您的朋友指的是他的房子,而您认为他指的是您的房子,那么您可能会感到困惑。如果在一个函数内部使用的变量与在另一个函数内部使用的变量具有相同的名称,并且两者不打算引用相同的值,那么在 Lisp 中也可能会发生同样的情况。let 特殊形式可以防止这种混乱。
\n-- http://www.gnu.org/software/emacs/manual/html_node/eintr/let.html
\n
| 归档时间: |
|
| 查看次数: |
11306 次 |
| 最近记录: |