You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Common Lisp中let声明的变量无法在when条件中使用的原因

问题根因

这根本不是变量作用域问题,是你搞错了Common Lisp的基本语法规则:
Common Lisp属于Lisp-2方言,函数和变量分属两个独立的命名空间。S表达式里,括号包裹的列表第一个位置的符号,默认会被解释为函数名做调用处理,其余位置的符号才会被解释为变量取值。


你代码里的具体错误
  • 触发报错的核心错误在(when (= (found nil)))这一行:(found nil)这个S表达式里,found在括号的第一个位置,Lisp会尝试查找名为found的函数、传入参数nil执行,但你只通过let定义了同名的局部变量,从来没定义过叫found的函数,自然会抛出「函数未定义」的错误。
  • 这一行的逻辑也写得不对:=是专门用来比较数值是否相等的运算符,你要判断found是不是nil,根本不需要套=,直接写(not found)就可以——Lisp里nil是唯一的假值,not会直接判断参数是否为假。
  • 就算你过了前面的报错,下一行(setq *new-list* (list(firstlocation)))还会触发同类错误:(firstlocation)把变量firstlocation放在括号首位,Lisp又会去找名为firstlocation的函数调用,继续报未定义错误。

你写的第二段代码能正常运行也很好解释:(print found)里found是作为print函数的参数出现的,不在S表达式的第一个位置,Lisp会正确把它识别为变量、取它绑定的值传给print,自然不会报错。


修正后的代码
(defun upsi()
  (let ((firstpos (car *old-list*)) 
        (secondpos (car (cdr *old-list*))))
    (let ((found nil)
          (secondlocation (list (car (cdr firstpos)) (car secondpos))))
      (when (not found)
        (setq *new-list* (list secondlocation))))))

新手避坑提醒
  • 不要随便给变量加多余的括号:var代表取变量var的值,(var)代表调用无参函数var,(var arg)代表调用函数var并传入参数arg,三者语义完全不同。
  • 选对等值判断运算符:=仅用于数值比较,比较通用对象是否相等用eql/equal,判断值是否为nil直接用not/null即可。

内容的提问来源于stack exchange,提问作者sergeantSalty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 18:22:21