我们可以做很多事情来改进这段代码。
您可以采取一些措施来改善您的问题。如果您再问,请提供测试用例和具体问题。
-
缩进
Lisp 的语法相对较少,但我们使用缩进来帮助突出代码的结构。大多数支持 Lisp 的编辑器都会帮助管理它。与传统缩进方法最明显的不同是以下行的右括号。我缩进了 mergelist 函数以显示更易读的函数体 - 至少对我来说是这样。
(defun bubble (lis)
(let ((sorted nil) (j 0))
(do () ((not sorted))
(progn
(setf sorted t)
(do (i j (+ i 1))
(if (< (nth i lis) (nth (+ i 1) lis))
(progn
(swap1 (lis (nth i lis) (nth (+ i 1) lis)))
(setf sorted nil))))))))
循环与 DO
DO 在 lisp 中有着悠久的血统,但说实话,我总是用 DO 出错,所以不要经常使用它。我永远不记得返回表格的去向,增量。我倾向于使用循环
但首先,我们不需要使用 progn。大多数循环结构对它们正在迭代的代码都有一个隐含的预测,所以
(defun bubble-1 (lis)
(let ((sorted nil) (j 0))
(do () ((not sorted))
(setf sorted t)
(do (i j (+ i 1))
(if (< (nth i lis) (nth (+ i 1) lis))
(swap1 (lis (nth i lis) (nth (+ i 1) lis)))
(setf sorted nil))))))
稍微好一点。查看您的代码,有对 swap1 的调用,它必须是某处提供的 defun。这行代码也有语法问题,因为 'lis' 以函数调用的形式出现。
让我们尝试评估函数并看看会发生什么
; in: DEFUN BUBBLE-1
; (LET ((SORTED NIL) (J 0))
; (DO ()
; ((NOT SORTED))
; (SETF SORTED T)
; (DO (I
; J
; (+ I 1))
; (IF (< # #) (SWAP1 #) (SETF #)))))
;
; caught STYLE-WARNING:
; The variable J is defined but never used.
; in: DEFUN BUBBLE-1
; (DO (I
; J
; (+ I 1))
; (IF
; (< (NTH I LIS) (NTH (+ I 1) LIS))
; (SWAP1 (LIS (NTH I LIS) (NTH # LIS)))
; (SETF SORTED NIL)))
; --> BLOCK
; ==>
; (LET (I J (+ I))
; (TAGBODY
; (GO #:G3)
; #:G2
; (TAGBODY)
; (PSETQ + 1)
; #:G3
; (UNLESS IF (GO #:G2))
; (RETURN-FROM NIL (PROGN (< # #) (SWAP1 #) (SETF #)))))
;
; caught WARNING:
; undefined variable: I
; --> BLOCK LET TAGBODY UNLESS
; ==>
; (IF IF
; NIL
; (GO #:G2))
;
; caught WARNING:
; undefined variable: IF
; (LIS (NTH I LIS) (NTH (+ I 1) LIS))
;
; caught STYLE-WARNING:
; undefined function: LIS
; (SWAP1 (LIS (NTH I LIS) (NTH (+ I 1) LIS)))
;
; caught STYLE-WARNING:
; undefined function: SWAP1
;
; compilation unit finished
; Undefined functions:
; LIS SWAP1
; Undefined variables:
; I IF
; caught 2 WARNING conditions
; caught 3 STYLE-WARNING conditions`enter code here`
哇。这告诉我们一些事情
- 未使用嵌套 DO 中的变量 J。删除它。
-
嵌套循环中的 DO 语法错误。它必须是一般形式
(DO ((var init step))
(termination-test result-form)
statement)
嵌套的 do 缺少终止测试。 i 的变量声明也缺少初始化。
-
Let 有点多余,你可以将 sorted 的声明移到 do 中
(do ((sorted nil)) ((not sorted ) ... )
-
表格
(SWAP1 (LIS (NTH I LIS) (NTH (+ I 1) LIS)))
有两个问题。首先 SWAP1 是未定义的。其次,形式 (LIS (NTH I LIS) (NTH (+ I 1) LIS)) 不可能是正确的,因为 LIS 出现在函数调用位置。出现在表单前面的任何东西都必须是函数。在这种情况下,LIS 是一个参数。
幸运的是,Common Lisp 有一个内置函数,可以为我们交换值 - 它称为 rotatef。所以整个表单需要看起来像
(rotatef (nth I lis) (nth (1+ i) lis))
- 一旦函数运行,它在do中没有结果形式,所以排序后的数组永远不会返回给调用者。您将看不到任何输出。您需要考虑一下您在此处嵌套循环的事实。
我会考虑一下您的算法。正如 Zephyr Pellerin 上面所说,递归解决方案会更好,所以除非您的任务是使用迭代解决方案