Lisp编写swap列表交换函数运行报参数过多错误如何解决
错误原因
- 首先你看到的
*** - EVAL/APPLY: too many arguments given to SWAP报错,是因为REPL中保留了你之前定义的参数数量更少的swap函数,你当前写的这个swap因为内部语法错误没有成功覆盖旧定义,调用时触发了旧函数的参数校验错误。你可以先执行(fmakunbound 'swap)清除旧的函数定义,就能看到代码的真实报错。 - 你的
swap函数本身存在两处核心问题:- Common Lisp的
substitute函数要求传入3个必填参数:(substitute 新值 旧值 目标序列),你当前的两次substitute调用都漏传了第三个目标序列参数,属于语法错误。 - 逻辑层面存在缺陷:
substitute是纯函数,只会返回修改后的新序列,不会修改原序列,你第一次调用substitute的结果没有被保存,第二次调用依旧基于原列表操作,无法实现交换效果;同时substitute是按值匹配替换,只要和旧值相同的元素都会被替换,不能精准替换指定位置的元素,列表存在重复值时会出问题。
- Common Lisp的
修复方案
推荐使用按索引遍历的方式实现,精准匹配位置,不受重复值影响,符合函数式编程返回新列表的要求:
(defun swap (lst x y) ;; 确保x是较小的索引,避免重复取值逻辑(可选优化) (when (> x y) (rotatef x y)) (loop for idx from 0 for elem in lst collect (cond ((= idx x) (nth y lst)) ((= idx y) (nth x lst)) (t elem))))
测试调用:
(swap '(1 2 3 4 5 e 6 7 8) 5 4)
返回结果为:(1 2 3 4 E 5 6 7 8),符合预期。
内容的提问来源于stack exchange,提问作者Lan
相关产品推荐
相关产品推荐

