Common lisp setq与未声明的自由变量(公共lisp)

Common lisp setq与未声明的自由变量(公共lisp),common-lisp,Common Lisp,我是个口齿不清的人,所以请温柔一点 我很难理解CL关于[un-]声明自由变量的想法。我认为: (defun test () (setq foo 17) ) 将定义一个声明变量foo并将其设置为17的函数。然而,我得到的却是 ;Compiler warnings : ; In TEST: Undeclared free variable FOO 我的实际案例要大一点;我的代码片段如下所示: (defun p8 () ;;; [some other stuff, snip]

我是个口齿不清的人,所以请温柔一点

我很难理解CL关于[un-]声明自由变量的想法。我认为:

(defun test ()
    (setq foo 17)
)
将定义一个声明变量foo并将其设置为17的函数。然而,我得到的却是

;Compiler warnings :
;  In TEST: Undeclared free variable FOO
我的实际案例要大一点;我的代码片段如下所示:

(defun p8 ()
    ;;; [some other stuff, snip]

    (loop for x from 0 to (- (length str) str-len) do
        (setq last (+ x str-len))           ; get the last char of substring
        (setq subs (subseq str x last))     ; get the substring
        (setq prod (prod-string subs))      ; get the product of that substring
        (if (> prod max)                    ; if it's bigger than current max, save it
            (setq max prod)
            (setq max-str subs)
        )
    )

;;; [More stuff, snip]
)
(loop for x from 0 to (- (length str) str-len) do
    (let* ((last (+ x str-len))         ; get the last char of substring
           (subs (subseq str x last))   ; get the substring
           (prod (prod-string subs)))   ; get the product of that substring
      (if (> prod max)                    ; if it's bigger than current max, save it
          (setq max prod)
          (setq max-str subs))))
这给了我:

;Compiler warnings for "/path/to/Lisp/projectEuler/p6-10.lisp":
;   In P8: Undeclared free variable LAST (2 references)
;Compiler warnings for "/Volumes/TwoBig/AllYourBits-Olie/WasOnDownBelowTheOcean/zIncoming/Lisp/projectEuler/p6-10.lisp" :
;   In P8: Undeclared free variable PROD (3 references)
;Compiler warnings for "/Volumes/TwoBig/AllYourBits-Olie/WasOnDownBelowTheOcean/zIncoming/Lisp/projectEuler/p6-10.lisp" :
;   In P8: Undeclared free variable SUBS (3 references)
;Compiler warnings for "/Volumes/TwoBig/AllYourBits-Olie/WasOnDownBelowTheOcean/zIncoming/Lisp/projectEuler/p6-10.lisp" :
;   In P8: Undeclared free variable =
是的,是的,我意识到我使用了太多的中间变量,但我试图在我太喜欢将所有内容压缩到最小类型的字符之前了解发生了什么,这在CL世界中似乎很流行

所以,不管怎样。。。有人能解释一下吗

Lisp在什么条件下声明变量? 是所述变量的范围,而不是封闭的。。。围绕setq声明?!也就是说,我希望var是有效的&适用于从。。。setq。。。帕伦斯1级在setq之外,不是吗? 我是否错误地解释了未声明的自由变量消息? 你想给我的任何其他提示都会帮助我更好地了解这里发生了什么。 注意:我相当精通C、Java、Javascript、Obj-C和相关的过程语言。我知道函数式编程是不同的。现在,我只是在努力学习语法

谢谢


另外,如果有关系的话,defunp8在一个文本文件TextMate中,我正在Clozure CL上运行它。不过,希望这些都不重要

在Lisp中,变量声明可以通过多种方式执行。最值得注意的是:

声明全局变量时,它们被正确地称为带有defparmeter和defvar的特殊变量 使用let、let*、多值绑定、解构绑定和其他绑定形式声明局部变量 作为函数参数 您也可以在许多地方了解它们的范围,例如在

setq/setf不是变量声明操作符,而是变量修改操作符,正如它们的名称所暗示的那样


PS.在交互模式下,如果您试图设置未声明的变量,某些实现会使用DWIM方法,并在后台将变量声明为特殊变量,但这纯粹是为了方便。

在lisp中,变量可以使用defParameterOrdefVar声明

这将产生全局动态变量

DEFVAR和DEFParameters之间的差异在于DEFVAR不会重新初始化已存在的变量

引入局部词法变量,例如使用let或let*按顺序初始化变量

未声明的自由变量表示您在此处使用了一个变量,该变量未绑定到所使用的上下文中。然后,它可能会为您声明,但可能会作为一个全局动态变量。这样做的结果是,如果在多个函数中使用具有相同名称的未声明变量,则在所有函数中都将引用相同的变量

您的代码可以这样编写:

(defun p8 ()
    ;;; [some other stuff, snip]

    (loop for x from 0 to (- (length str) str-len) do
        (setq last (+ x str-len))           ; get the last char of substring
        (setq subs (subseq str x last))     ; get the substring
        (setq prod (prod-string subs))      ; get the product of that substring
        (if (> prod max)                    ; if it's bigger than current max, save it
            (setq max prod)
            (setq max-str subs)
        )
    )

;;; [More stuff, snip]
)
(loop for x from 0 to (- (length str) str-len) do
    (let* ((last (+ x str-len))         ; get the last char of substring
           (subs (subseq str x last))   ; get the substring
           (prod (prod-string subs)))   ; get the product of that substring
      (if (> prod max)                    ; if it's bigger than current max, save it
          (setq max prod)
          (setq max-str subs))))
使用循环的变量绑定属性,它也可以写成

(loop for x from 0 to (- (length str) str-len)
      for last = (+ x str-len)
      for subs = (subseq str x last)
      for prod = (prod-string subs)
      when (> prod max) do
          (setq max prod)
          (setq max-str subs))

Common Lisp HyperSpec基本上是HTML格式的Common Lisp标准:

为变量赋值

所以SETQ只给变量赋值。它没有申报

变量定义使用DEFVAR、DEFPARAMETER等全局执行

变量定义是通过DEFUN、LET、LET*、LOOP和许多其他方法在本地完成的

(defun foo (v1 v2)
  ...)

(let ((v1 10)
      (v2 20))
  ...)

(loop for v1 in '(10 30 10 20)
      do ...)
这是基本的Lisp,阅读介绍会很有用。我建议:

以上书免费下载

此外,上面提到的通用Lisp Hyperspec为您提供了通用Lisp的定义,并描述了各种工具DEFUN、LOOP、DEFPARAMETER等。。。详细地说