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

SBCL报“STR函数未定义”错误:字符串去重空格问题求助

问题

环境:Windows 11,PowerShell中运行Steel Bank Common Lisp(SBCL)2.0.0版本的REPL

我编写了一个用于去除字符串多余空格的函数(目标是将"This is a string"转换为"This is a string"),代码如下:

(defun trim-spaces (str)
   (let* 
     ((len (length(str))) 
     (i 1)
     (last-char (char str (- 1 i)))
     (curr-char (char str i)) )
  
     (dotimes (i len) 
        (cond 
           ((eql last-char #\Space)
              (cond 
                 ((eql curr-char #\Space)
                    (setq str (remove curr-char str)))))))))

(trim-spaces "This   is  a string")

此前编写的类似功能函数(如去除字符串括号的函数)均可正常运行,但执行上述代码时,无论传入字符串字面量还是变量,都会触发以下错误:

debugger invoked on a UNDEFINED-FUNCTION @1000000C2C in thread
#<THREAD tid=19952 "main thread" RUNNING {1100BC8003}>:
The function COMMON-LISP-USER::STR is undefined.

想了解该问题的成因,以及对应的解决或规避方法。


解答

问题成因

当前错误的直接原因是语法错误:Common Lisp的函数调用语法要求函数名与参数之间必须用空格分隔,你写的(length(str))会被解析为「调用名为STR的函数,并把length作为它的参数」,但你并没有定义过STR函数,因此触发未定义函数错误。

除此之外,你的函数还存在逻辑缺陷:

  1. let*中初始化的i=1会被dotimes重新绑定的局部变量i覆盖,导致初始定义的last-char和curr-char只会取字符串固定位置的字符,不会随循环更新;
  2. (remove curr-char str)会删除字符串中所有空格,而非仅连续的多余空格,无法实现预期功能。

解决方法

1. 修复语法错误(解决当前报错)

将(length(str))修改为(length str),严格遵循Common Lisp函数调用的语法规范。

2. 修正函数逻辑(实现预期功能)

以下提供两种可行的实现方式:

方式一:原生Common Lisp实现(无第三方依赖)

手动遍历字符串,构建仅保留单个连续空格的结果:

(defun trim-spaces (str)
  (with-output-to-string (out)
    (let ((last-space-p nil))
      (loop for char across str
            do (cond
                 ((char= char #\Space)
                  (unless last-space-p
                    (write-char char out)
                    (setf last-space-p t)))
                 (t
                  (write-char char out)
                  (setf last-space-p nil)))))))

逻辑说明:

  • 用with-output-to-string创建字符串输出流,便捷构建结果;
  • 用last-space-p标记上一个字符是否为空格;
  • 遍历每个字符:若为空格,仅在上一个字符不是空格时写入;若非空格字符,直接写入并重置标记。

测试验证:

(trim-spaces "This   is  a string") ; 返回 "This is a string"

方式二:使用正则表达式(依赖第三方库cl-ppcre)

若允许使用第三方库,cl-ppcre的正则替换功能可以更简洁地实现需求:

(ql:quickload :cl-ppcre) ; 先加载库
(defun trim-spaces (str)
  (cl-ppcre:regex-replace-all "\\s+" str " "))

规避方法

  • 编写Common Lisp代码时,严格遵守函数调用语法:函数名与参数列表之间必须用空格分隔,不要沿用C语言风格的函数名(参数)写法;
  • 调试时优先查看错误提示的第一行内容,通常会直接指出未定义函数或语法错误的位置,快速定位问题。

内容的提问来源于stack exchange,提问作者Ashley Ben Story

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 14:25:01