setq vs未声明的自由变量(通用lisp) [英] setq vs Undeclared free variable (common lisp)

查看:89
本文介绍了setq vs未声明的自由变量(通用lisp)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我总共是Lisp n00b,所以请保持温柔。

I'm a total Lisp n00b, so please be gentle.

我很难理解CL的[un-]宣布免费的想法。变量。我认为:

I'm having trouble wrapping my head around CL's idea of an [un-]declared free variable. I would think that:

(defun test ()
    (setq foo 17)
)

将定义一个函数,该函数声明一个变量foo并将其设置为17。但是,相反,我得到了

would define a function that declares a variable foo and set it to 17. However, instead I get

;Compiler warnings :
;  In TEST: Undeclared free variable FOO

我的实际示例案例更大;我的代码(摘要)如下:

My actual example case is a bit bigger; my code (snippet) looks like this:

(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世界中一样。

Yes, yes, I realize that I'm using far too many intermediate variables, but I'm trying to understand what's going on before I get too fancy with compressing everything down to the minimal typed characters, as seems popular in the CL world.

因此,无论如何...有人可以解释以下内容:

So, anyway... can someone explain the following:


  • 在什么条件下Lisp会声明变量?

  • 除了包围 setq (...)以外,所述变量的范围是>声明?! (也就是说,我希望var对(...(setq ...)...)范围内的所有内容都是有效的&范围为 setq ,不是吗?

  • 我误解了未声明的自由变量消息吗?

  • 您想提供的其他任何提示都可以帮助我更好地了解发生了什么事情。

  • Under what conditions does Lisp "declare" a variable?
  • Is the scope of said variable other than the enclosing (...) around the setq statement?! (That is, I would expect the var to be valid & scoped for everything from (... (setq ...) ...) the parens 1 level outside the setq, no?
  • Am I mis-interpreting the Undeclared free variable message?
  • Any other hints you care to give that would help me better grok what's going on, here.

注意:我对C,Java,Javascript,Obj-C和相关的过程语言相当熟练。我发现函数式编程是不同的。就目前而言,我只是在努力使用语法。

NOTE: I'm fairly expert with C, Java, Javascript, Obj-C, and related procedural languages. I get that functional programming is different. For now, I'm just wrestling with the syntax.

谢谢!

PS如果很重要, defun p8 在文本文件中(TextMate),我正在 Clozure CL 上运行它。希望这没关系!

P.S. If it matters, defun p8 is in a text file (TextMate) and I'm running it on Clozure CL. Hopefully, none of that matters, though!

推荐答案

在Lisp变量中,可以使用 defparameter defvar 声明。

In lisp variables may be declared usingdefparameterordefvar.

(defparameter var1 5)
(defvar var2 42)

这将导致全局(动态)变量。

This results in global (dynamic) variables.

defvar 和<$之间的差c $ c> defparameter 是 defvar 不会重新初始化已经存在的变量。

The difference between defvarand defparameteris that defvardoes not reinitialize an already existing variable.

使用 let let * (初始化)在 eg 中引入局部(词法)变量

Local (lexical) variables are introduced e.g using let or let* (which initializes the variables sequentially).

未声明的自由变量表示您已使用过(这里 setq -ed)一个变量,该变量在使用它的上下文中未绑定。然后可以为您声明它,但随后可能将其声明为全局(动态)变量。这样的结果是,如果您在多个函数中使用具有相同名称的未声明变量,则将在所有函数中引用相同的 变量。

Undeclared free variable means that you have used (here setq-ed) a variable that it is not bound in the context it is used. It may then be declared for you, but then probably as a global (dynamic) variable. The consequence of this is that if you use undeclared variables with the same name in several functions, you will be referencing the same variable in all of the functions.

您的代码可以这样写:

(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))))

使用循环的变量绑定属性,

Using the variable-binding properties of loop, it may also be written as

(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))

这篇关于setq vs未声明的自由变量(通用lisp)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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