【问题标题】:getting 'undefined variable' warning, eventhough its defined得到“未定义的变量”警告,即使它已定义
【发布时间】:2023-04-11 09:08:01
【问题描述】:

在 sbcl repl 中执行以下代码时,我收到变量测试用例 n 的“未定义变量”警告。我已经在论坛上解决了类似的问题,如果变量在没有先定义的情况下被 setf/setq'ed ,就会出现警告。但是我已经使用 defparameter 定义了这些变量,但仍然收到警告。

我注意到的一件事是,如果我不引用格式语句中的变量,则不会出现警告。 我也尝试过使用 defvar 。但它仍在发出警告。 有人可以帮我理解为什么即使定义了变量,在语句中使用时也会引发警告?

    (defun main ()
           (defvar test-cases 10)
           (defvar l 12)
           (defvar n 13)
           (format t "~a ~a ~a" test-cases l n))
; in: DEFUN MAIN
;     (FORMAT T "~a ~a ~a" TEST-CASES L N)
; 
; caught WARNING:
;   undefined variable: N
; 
; caught WARNING:
;   undefined variable: TEST-CASES
; 
; compilation unit finished
;   Undefined variables:
;     N TEST-CASES
;   caught 2 WARNING conditions
WARNING: redefining COMMON-LISP-USER::MAIN in DEFUN

【问题讨论】:

标签: common-lisp sbcl


【解决方案1】:

下面解释了为什么你有一个错误,但请注意很少需要从内部函数定义全局变量,大多数时候你会使用LET的局部绑定。

这是一个简化的测试用例:

(defun foo () (defvar bar nil) bar)

在编译 foo 时,bar 未定义(假设是全新的 CL 环境)。这就是编译器抱怨的原因。但是,如果您调用 foo,则将(全局)声明该变量,然后返回其值。

DEFVAR 的调用仅在执行时才会对全局环境产生影响,或者在编译时当它是顶级表单时:

但是,下面描述的编译时副作用仅在它们显示为顶级表单时发生。

...

副作用:如果defvardefparameter 表单作为顶级表单出现,编译器必须认识到该名称已被宣布为特殊名称。但是,它既不能评估初始值形式,也不能在编译时分配名为 name 的动态变量。

因此,在函数体内编译对defvar 的调用不会将该符号声明为特殊变量。

【讨论】:

    猜你喜欢
    • 2023-01-11
    • 1970-01-01
    • 2019-04-08
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    • 2022-01-21
    • 2015-01-21
    • 1970-01-01
    相关资源
    最近更新 更多