Common Lisp中使用if条件向列表添加元素的问题排查
解决Lisp列表筛选超出限制元素的问题
你的代码有几个关键问题导致结果不符合预期,下面逐一说明并给出修正方案:
原代码的问题
- 逻辑判断完全错误:你要筛选的是「小于2或大于5」的元素,但原
limits函数的条件写反了——任何数字要么大于2,要么小于5,等于所有元素都会被选中,而且还错误地把元素包装成了嵌套列表((list x))。另外函数没有明确返回结果,Lisp默认返回最后一个表达式的值,原函数最后是(),实际返回nil,这和你预期的完全不符。 - 函数调用缺少括号:
out-of-limits里的mapcar #'limits l没有加括号,Lisp中函数调用必须用括号包裹,否则只是返回符号和参数列表,根本没执行mapcar。 - 滥用全局变量:用
setq直接赋值out会修改全局变量,这是Lisp编程的不良习惯,应该用局部变量或者直接返回计算结果。
修正后的实现
方案1:用谓词函数+remove-if-not(推荐)
先写一个判断元素是否超出限制的谓词函数(Lisp中约定返回布尔值的函数以-p结尾):
(defun out-of-limits-p (x) (or (< x 2) (> x 5)))
然后用remove-if-not筛选列表,这个函数会保留所有满足谓词的元素:
(defun filter-out-of-limits (l) (remove-if-not #'out-of-limits-p l))
方案2:用mapcar+过滤nil
如果你想用mapcar实现,可以用lambda表达式处理每个元素,再去掉nil结果:
(defun filter-out-of-limits (l) (remove nil (mapcar (lambda (x) (when (or (< x 2) (> x 5)) x)) l)))
测试示例
调用(filter-out-of-limits '(1 3 6 2 5 0)),会返回(1 6 0),这就是你要的超出限制的元素列表。
内容的提问来源于stack exchange,提问作者M1ctl4nt3cutl1
相关产品推荐
相关产品推荐

