在 Lisp 中为全局变量赋值
Assigning values to global variables in Lisp
我是 Lisp 的新手,我想了解变量和分配变量的工作原理。我正在尝试检查给定数字是否为 5。如果是,则应该将其更改为 10 并打印出来。如果不是,它只是告诉你它不是 5,但我下面的代码不起作用。
(print "Give me a number")
(setq *x* (read))
(defun check(*x*)
(if (= *x* 5) (setq *x* 10) (format t "~d is not 5" *x*))
)
check(*x*)
print(*x*)
check(*x*)
和 print(*x*)
不是 Lisp 语法。将其替换为 (check *x*)
和 (print *x*)
- 您的函数使用一些
*x*
,但它 不是 您的全局 *x*
,而是参数列表中的局部变量 *x*
.不要将函数参数命名为与全局变量相同的名称。检查这个例子:
(defparameter a 8)
(defun add (a)
(setf a (+ a 2))
(print a))
(add a)
(print a)
返回值为 10,然后是 8。将其与:
进行比较
(defparameter *a* 8)
(defun add (a)
(setf *a* (+ *a* 2))
(print *a*))
(add *a*)
(print *a*)
返回值为 10 和 10。
- 不要使用
setf
或setq
来创建变量,这些函数仅用于设置新值。请改用 defparameter or defvar。
- 此代码为全局变量赋值:
(print "Give me a number")
(defparameter *x* (read *query-io*))
(defun check ()
(if (= *x* 5)
(setf *x* 10)
(format t "~d is not 5" *x*)))
(check)
(print *x*)
- 您也可以在没有全局变量的情况下完成此任务。
(print "Give me a number")
(defun check (n)
(if (= n 5)
(setf n 10)
(format t "~d is not 5" n))
(print n))
(check (read *query-io*))
如果我在 SBCL 中用这个定义编译一个文件:
(print "Give me a number")
(setq *x* (read))
(defun check(*x*)
(if (= *x* 5) (setq *x* 10) (format t "~d is not 5" *x*))
)
有两个警告:
warning: undefined variable: *X*
这位于全局 setq
,因为 setq
不 声明 全局变量。所以编译器不知道任何名为 *x*
.
的全局变量
然后,函数内部:
style-warning:
using the lexical binding of the symbol (*X*), not the
dynamic binding, even though the name follows
the usual naming convention (names like *FOO*) for special variables
--> PROGN SB-IMPL::%DEFUN SB-IMPL::%DEFUN SB-INT:NAMED-LAMBDA
==>
#'(SB-INT:NAMED-LAMBDA AAAB::CHECK
(*X*)
(DECLARE (SB-C::TOP-LEVEL-FORM))
(BLOCK CHECK
(IF (= *X* 5)
(SETQ *X* 10)
(FORMAT T "~d is not 5" *X*))))
这是不言自明的,但这里的绑定是词法的。
但这不是 defun
的 属性,这是因为没有声明名为 *x*
.
的特殊变量
如果您改为使用 defvar
或 defparameter
,则不会出现警告(例如 (defvar *x* 0)
)。如果您仅将变量声明为特殊变量,情况也是如此:(declaim (special *x*))
,然后再定义绑定它的函数。
在函数内部,假设 *x*
被声明为特殊变量,绑定作为 let
,这意味着您可以使用特殊变量作为函数参数。在您的情况下,这并没有太大变化,因为您只使用内部 setq
设置当前绑定(参数隐藏全局绑定),所以实际上这很像词法变量。
但是你可以使用一个特殊的变量来动态地重新绑定一个参数:
(defun foo (*a*) ...)
这等同于:
(defun foo (a)
(let ((*a* a))
...))
我是 Lisp 的新手,我想了解变量和分配变量的工作原理。我正在尝试检查给定数字是否为 5。如果是,则应该将其更改为 10 并打印出来。如果不是,它只是告诉你它不是 5,但我下面的代码不起作用。
(print "Give me a number")
(setq *x* (read))
(defun check(*x*)
(if (= *x* 5) (setq *x* 10) (format t "~d is not 5" *x*))
)
check(*x*)
print(*x*)
check(*x*)
和print(*x*)
不是 Lisp 语法。将其替换为(check *x*)
和(print *x*)
- 您的函数使用一些
*x*
,但它 不是 您的全局*x*
,而是参数列表中的局部变量*x*
.不要将函数参数命名为与全局变量相同的名称。检查这个例子:
(defparameter a 8)
(defun add (a)
(setf a (+ a 2))
(print a))
(add a)
(print a)
返回值为 10,然后是 8。将其与:
进行比较(defparameter *a* 8)
(defun add (a)
(setf *a* (+ *a* 2))
(print *a*))
(add *a*)
(print *a*)
返回值为 10 和 10。
- 不要使用
setf
或setq
来创建变量,这些函数仅用于设置新值。请改用 defparameter or defvar。 - 此代码为全局变量赋值:
(print "Give me a number")
(defparameter *x* (read *query-io*))
(defun check ()
(if (= *x* 5)
(setf *x* 10)
(format t "~d is not 5" *x*)))
(check)
(print *x*)
- 您也可以在没有全局变量的情况下完成此任务。
(print "Give me a number")
(defun check (n)
(if (= n 5)
(setf n 10)
(format t "~d is not 5" n))
(print n))
(check (read *query-io*))
如果我在 SBCL 中用这个定义编译一个文件:
(print "Give me a number")
(setq *x* (read))
(defun check(*x*)
(if (= *x* 5) (setq *x* 10) (format t "~d is not 5" *x*))
)
有两个警告:
warning: undefined variable: *X*
这位于全局 setq
,因为 setq
不 声明 全局变量。所以编译器不知道任何名为 *x*
.
然后,函数内部:
style-warning:
using the lexical binding of the symbol (*X*), not the
dynamic binding, even though the name follows
the usual naming convention (names like *FOO*) for special variables
--> PROGN SB-IMPL::%DEFUN SB-IMPL::%DEFUN SB-INT:NAMED-LAMBDA
==>
#'(SB-INT:NAMED-LAMBDA AAAB::CHECK
(*X*)
(DECLARE (SB-C::TOP-LEVEL-FORM))
(BLOCK CHECK
(IF (= *X* 5)
(SETQ *X* 10)
(FORMAT T "~d is not 5" *X*))))
这是不言自明的,但这里的绑定是词法的。
但这不是 defun
的 属性,这是因为没有声明名为 *x*
.
如果您改为使用 defvar
或 defparameter
,则不会出现警告(例如 (defvar *x* 0)
)。如果您仅将变量声明为特殊变量,情况也是如此:(declaim (special *x*))
,然后再定义绑定它的函数。
在函数内部,假设 *x*
被声明为特殊变量,绑定作为 let
,这意味着您可以使用特殊变量作为函数参数。在您的情况下,这并没有太大变化,因为您只使用内部 setq
设置当前绑定(参数隐藏全局绑定),所以实际上这很像词法变量。
但是你可以使用一个特殊的变量来动态地重新绑定一个参数:
(defun foo (*a*) ...)
这等同于:
(defun foo (a)
(let ((*a* a))
...))