是的,你猜对了。你需要一个宏。
(defmacro reassign (var &optional (val 10)) `(setq ,var ,val))
(defvar s ()) ;; @Svante remarked that setq can be dangerous to create a variable
s ;; NIL
(reassign s)
s ;; 10
;; the `&optional (val 10)` makes the value optional and 10 to the
;; default value of val if not given.
在你的例子中
(defun reassign (val) (setq val 10))
val 是 setq 特殊形式的第一个参数:setq 中的 val 不会变成 s,尽管您将 reassign 指定为 val。它保持为val,以便您将功能范围内的10 分配给val。您可以通过以下方式使其可见:
(setq s ())
(defun reassign (val)
(print "You gave for `val`:")
(print val)
(setq val 10)
(print "The form assigned 10 literally to val")
(print "Proof: Print out val in this scope:")
(print val))
(reassign s)
;;
;; "You gave for `val`:"
;; NIL
;; "The form assigned 10 literally to val"
;; "Proof: Print out val in this scope:"
;; 10
;; 10
(print val)
*** - SYSTEM::READ-EVAL-PRINT: variable VAL has no value
The following restarts are available:
USE-VALUE :R1 Input a value to be used instead of VAL.
STORE-VALUE :R2 Input a new value for VAL.
ABORT :R3 Abort main loop
;; since val has not been initiated before
另外,函数的setq是在函数范围内执行的。这就是为什么在函数 val 之外保留旧值的原因。
(defvar val ()) ;; NIL
(print val) ;; NIL
(defun reassign (val)
(print "You gave for `val`:")
(print val)
(setq val 10)
(print "The form assigned 10 literally to val")
(print "Proof: Print out val in this scope:")
(print val))
(reassign 'whatever) ;; inside function val becomes 10
;;
;;"You gave for `val`:"
;;WHATEVER
;;"The form assigned 10 literally to val"
;;"Proof: Print out val in this scope:"
;;10 ;; val becomes indeed 10 until leaving function
;;10
;; but retains old value after leaving the function
(print val)
;;
;; NIL
;; NIL
相比之下,宏将(reassign s) 的宏调用替换为(setq s 10) 形式。因此,在执行时,重新分配发生在我们定义(defvar s ()) 的环境中。
因此,在重新分配后,s 会保留新分配的值,因为它是在工作环境中重新分配的。