使用setf,defvar,let和scope分配变量 [英] Assigning variables with setf, defvar, let and scope

查看:85
本文介绍了使用setf,defvar,let和scope分配变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我从

setq和defvar in lisp中读到了

http:// www .cs.ucf.edu / courses / cop4020 / spr2006 / plsetup.html



除其他地方外,还涉及到setf之间的区别和defvar。因此,我决定稍微考虑一下这个想法:

So, I have read from
setq and defvar in lisp,
http://www.cs.ucf.edu/courses/cop4020/spr2006/plsetup.html, and
In Lisp, how do I fix "Warning: Assumed Special?"
among other places about the difference between setf and defvar. So I decided to play around with the idea a bit:

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来更改现有变量,但未定义的变量警告似乎在SBCL中处理得很好(尽管我已经读过,不同的CL实现可能会对此进行不同的处理,因此这不是最好的选择)。

Okay, I know that setf should be used to change the value of an existing variable, but the undefined variable warning seems to be handled pretty well in SBCL (though I have read that different CL implementations may handle this differently, thus it isn't the best thing to do).

输入第二个测试:

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,我认为应该一次创建并绑定变量。现在,我未定义的变量警告被推到(print y)行中...这是怎么回事?

As per the links, I changed the setf to defvar which I think should create and bind the variable all at once. Now my undefined variable warning gets pushed into the (print y) line ... what is going on here?

作为第二个问题,我希望得到任何值在函数内被赋值的变量在函数外部是不可访问的,如Python中那样:

As a secondary question, I am expecting the values of any variables assinged within a funciton to be inaccessible outside of the function, as is the case in 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

我想这有事情要做用普通的Lisp处理范围的方式,即defvar创建一个全局特殊变量 ...所以我最后一次尝试了(let ...)

I am guessing this has something to do with the way common lisp deals with scope, ie defvar creates a "global special variabe" ... So I tried one last time with (let ...)

CL -USER>(defun baz()
(let((z 10))(print z))
(incf z 10)
(print z))

CL-USER> (defun baz () (let ((z 10)) (print z)) (incf z 10) (print 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

并在阅读 defvar,defparameter,setf和setq之间有什么区别,这个似乎很正常:

And after reading What's difference between defvar, defparameter, setf and setq, this one seems to work right:

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进行,让?

2)是否有一种方法可以像在python示例中那样使通用lisp定义函数内部变量的范围?

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?

推荐答案

回答 2) DEFVAR 定义了一个变量。但它尚未执行。因此,编译器不知道 print 形式的变量-编译 DEFUN 形式时。。它也位于内部 DEFUN 。因此,它不在顶层。作为顶层形式,编译器将识别 DEFVAR 并会注意到 y 是全局特殊变量。 / p>

answering 2) DEFVAR defines a variable. But it has not been executed. So the compiler does not know about the variable in the print form - when compiling the DEFUN form.. It's also inside a DEFUN. Thus it is not on the top-level. As a top-level form the compiler would recognize the DEFVAR and would notice that y is a global special variable.


重申一下我的问题:1)setf,defvar和let到底发生了什么?
2)是否有一种方法可以像在python示例中那样获得通用Lisp来确定函数内部变量的范围?

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实现都会做一些有用的事情。通常,它的执行就像是将变量声明为特殊变量一样(因此您还会收到警告)。

1) SETF sets a variable value, but does not define it. If that variable is undefined, then the Common Lisp standard does not really say what happens. Most Common Lisp implementations will do something useful. Typically it gets executed as if the variable would have been declared special (thus you also get a warning).

DEFVAR 用作顶级形式(通常不在函数内部)定义全局特殊变量。由于 DEFVAR 声明变量名称特殊,因此写一个带有星号的变量是非常有用的约定: * y * 而不只是 y

DEFVAR is used as a top-level form (usually not inside functions) to define global special variables. Since DEFVAR declares the variable name to be special, it is a very useful convention to write a variable with stars around it: *y* instead of just y.

LET 定义局部变量的范围。

LET defines a scope for local variables.

2)常见的Lisp函数具有用于引入变量的参数列表。除此之外,他们没有定义变量范围。如果要在函数内引入局部变量,请使用 LET

2) Common Lisp functions have the parameter list to introduce variables. Other than that they don't define a variable scope. If you want to introduce a local variable inside a function, use LET.

>>> def foo():
...     x = 10
...     print x

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

再次:一个函数不提供变量作用域,例如分配一个函数内部的变量会自动将其定义为局部函数。请改用 LET

Again: a function does not provide a scope for variables, such that assigning a variable inside a function will automagically define it to be function-local. Use LET instead.

请注意, LET 句法糖,主要是:(let((a 1)(b 2))(+ ab))基本上与((lambda(ab)(+ ab))1 2)

Note also that LET is syntactic sugar, mostly: (let ((a 1) (b 2)) (+ a b)) is basically doing the same as ((lambda (a b) (+ a b)) 1 2). It's just a simple function application written differently to improve it for the human reader.

Common Lisp还支持较旧的语法:

There is also support in Common Lisp for an older syntax:

(defun foo (&aux (x 10))
  (print x))

上面定义了局部变量 X ,就像 LET 可以。

Above defines a local variable X, just like a LET would do.

这篇关于使用setf,defvar,let和scope分配变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆