我是一个完全的 Lisp n00b,所以请温柔一点。
我很难理解 CL 关于 [未] 声明的自由变量的想法。我会认为:
(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]
)
这给了我:
;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 对于 var(... (setq ...) ...)
之外的 parens 1 级别的所有内容都是有效的setq
,不是吗? - 我是否误解了未声明的自由变量消息?
- 您愿意提供的任何其他提示将帮助我更好地了解发生了什么,在这里。
注意:我非常精通 C、Java、Javascript、Obj-C 和相关的过程语言。我知道函数式编程是不同的。现在,我只是在与语法搏斗。
谢谢!
PS 如果重要的话,它defun p8
是在一个文本文件(TextMate)中,我正在运行它Clozure CL
。不过,希望这些都不重要!