与SETF,defvar,让和范围变量赋值(Assigning variables with set

2019-07-18 04:36发布

所以,我从读
setq和defvar在口齿不清 ,
http://www.cs.ucf.edu/courses/cop4020/spr2006/plsetup.html和
在Lisp,我怎么修复“警告:假设的特殊要求吗?”
当中约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应该用于更改现有变量的值,但未定义变量警告似乎在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我认为应该建立和可变一次性绑定。 现在我不确定变量警告被压入(打印Y)行...这到底是怎么回事呢?

作为一个次要的问题,我期待一个功能可按内assinged任何变量的值是无法访问的功能之外,由于是在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创建一个“全球特别variabe” ......所以,我想最后一次与(让...)

CL-USER>(defun定义的碱()(Y((10))(带有印记))(INCF 10)(带有打印内容))

; 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之间的区别 ,这其中似乎工作的权利:

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)有没有办法让Common Lisp的范围到一个函数内部的变量在Python的例子吗?

Answer 1:

回答2) DEFVAR定义的变量。 但它并没有被执行。 所以编译器不知道在可变print形式-编译时DEFUN形式。它也是一个内部DEFUN 。 因此,它是不是在顶层。 作为顶级形式,编译器会识别DEFVAR和会注意到y是一个全球性的特殊变量。

只是重申我的问题:1)什么是真正回事SETF,defvar和让? 2)有没有办法让Common Lisp的范围到一个函数内部的变量在Python的例子吗?

1) SETF设定的可变值,但不定义它。 如果变量未定义,那么Common Lisp的标准并没有真正说会发生什么。 最常见的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)) (+ ab))基本上是做相同((lambda (ab) (+ ab)) 1 2) 这只是有不同的写法简单的功能应用,提高其为人类的读者。

也有支持Common Lisp中一个旧的语法:

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

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



Answer 2:

我会尽量简短和简单的:

1)什么是真正回事SETF,defvar和让?

  • defvardefparameter用于声明和全局设置的特殊变量。 他们仅在名称已经绑定不同。

  • setf用于分配(特殊变量,词法变量,以及其他-可能为自定义- setfable地方)

  • let (和let* )创造了新的变量绑定是其体内可见。 它可以创建任何词汇或特殊的绑定,取决于(全局或局部)声明。 如果没有特别声明,词法绑定将被创建。

2)有没有办法让Common Lisp的范围到一个函数内部的变量在Python的例子吗?

把里面的代码let的身体,这里的绑定是可见的:

CL-USER> (defun baz ()
           (let ((z 10))
             (print z)
             (incf z 10) ; i.e. (setf z (+ z 10))
             (print z)))
BAZ
CL-USER> (baz)

10 
20 
20
CL-USER> z
; Evaluation aborted on #<UNBOUND-VARIABLE #x186C611E>.


文章来源: Assigning variables with setf, defvar, let and scope