gpt4 book ai didi

variables - 使用 setf、defvar、let 和范围分配变量

转载 作者:行者123 更新时间:2023-12-04 23:05:08 26 4
gpt4 key购买 nike

所以,我从
setq and defvar in lisp ,
http://www.cs.ucf.edu/courses/cop4020/spr2006/plsetup.html , 和
In Lisp, how do I fix "Warning: Assumed Special?"
在其他地方关于 setf 和 defvar 之间的区别。所以我决定尝试一下这个想法:

CL-USER> (defun foo ()
(setf x 10)
(print x))

; in: DEFUN FOO
; (SETF X 10)
; ==>
; (SETQ X 10)
;
; caught WARNING:
; undefined variable: X
;
; compilation unit finished
; Undefined variable:
; X
; caught 1 WARNING condition
FOO
CL-USER> x
; Evaluation aborted on #<UNBOUND-VARIABLE X {10040F1543}>.
CL-USER> (foo)

10
10
CL-USER> x
10

好的,我知道应该使用 setf 来更改现有变量的值,但是 undefined variable 警告似乎在 SBCL 中处理得很好(尽管我已经读过不同的 CL 实现可能会以不同的方式处理这个问题,因此它不是最好的办法)。

进入第二个测试:
CL-USER> (defun bar ()
(defvar y 15)
(print y))

; in: DEFUN BAR
; (PRINT Y)
;
; caught WARNING:
; undefined variable: Y
;
; compilation unit finished
; Undefined variable:
; Y
; caught 1 WARNING condition
BAR
CL-USER> y
; Evaluation aborted on #<UNBOUND-VARIABLE Y {10045033D3}>.
CL-USER> (bar)

15
15
CL-USER> y
15

根据链接,我将 setf 更改为 defvar 我认为应该一次创建和绑定(bind)变量。现在我的 undefined variable 警告被推送到 (print y) 行......这里发生了什么?

作为第二个问题,我希望函数内分配的任何变量的值在函数之外都无法访问,就像 Python 中的情况一样:
>>> def foo():
... x = 10
... print x
...
>>> foo()
10
>>> x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined

我猜这与 common lisp 处理范围的方式有关,即 defvar 创建了一个“全局特殊变量”......所以我最后一次尝试了 (let ...)

CL-USER>(defun baz()
(让 ((z 10)) (打印 z))
(incf z 10)
(打印 z))
; in: DEFUN BAZ
; (INCF Z 10)
; --> LET*
; ==>
; (SETQ Z #:NEW0)
;
; caught WARNING:
; undefined variable: Z
;
; compilation unit finished
; Undefined variable:
; Z
; caught 1 WARNING condition

看完 What's difference between defvar, defparameter, setf and setq ,这个似乎工作正常:
CL-USER> (defun apple ()
(defparameter x 10)
(print 10))

APPLE
CL-USER> x
; Evaluation aborted on #<UNBOUND-VARIABLE X {1004436993}>.
CL-USER> (apple)

10
10
CL-USER> x
10

只是重申我的问题:
1) setf、defvar 和 let 到底发生了什么?
2) 有没有办法让 common lisp 像 python 示例中那样在函数内限定变量?

最佳答案

接听 2) DEFVAR定义一个变量。但它没有被执行。所以编译器不知道 print 中的变量。表格 - 编译 DEFUN 时形式.. 它也在 DEFUN 内.因此它不在顶层。作为顶级形式,编译器将识别 DEFVAR并且会注意到 y是一个全局特殊变量。

Just to reiterate my questions: 1) what is really going on with setf, defvar and let? 2) is there a way to get common lisp to scope the variables inside a function as in the python example?



1) SETF设置一个变量值,但不定义它。如果该变量未定义,那么 Common Lisp 标准并没有真正说明会发生什么。大多数 Common Lisp 实现都会做一些有用的事情。通常它会像变量被声明为特殊一样被执行(因此您也会收到警告)。
DEFVAR用作定义全局特殊变量的顶级形式(通常不在函数内部)。由于 DEFVAR声明变量名是特殊的,写一个带有星号的变量是一个非常有用的约定: *y*而不仅仅是 y .
LET定义局部变量的范围。

2) Common Lisp 函数有参数列表来引入变量。除此之外,它们没有定义变量范围。如果要在函数中引入局部变量,请使用 LET .
>>> def foo():
... x = 10
... print x


(defun foo ()
(let ((x 10))
(print x)))

同样:函数不提供变量的作用域,因此在函数内部分配变量将自动将其定义为函数局部。使用 LET反而。

另请注意 LET是语法糖,主要是: (let ((a 1) (b 2)) (+ a b))((lambda (a b) (+ a b)) 1 2) 基本相同.它只是一个简单的函数应用程序,以不同的方式编写,以改进它以供人类读者使用。

Common Lisp 中还支持旧语法:
(defun foo (&aux (x 10))
(print x))

上面定义了一个局部变量 X , 就像 LET会做。

关于variables - 使用 setf、defvar、let 和范围分配变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14314834/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com