Lisp中未使用循环变量的处理方法及编码规范咨询
Lisp 按列表长度执行n次循环的优化方案
首先明确结论:你偏好的并行loop写法不需要放弃,它本身比调用list-length的常规写法性能更优,未使用变量的警告有非常成熟的标准方案解决,完全不需要为了消警告换回低效率写法。
两种写法的本质差异
先对比两种实现的运行逻辑:
- 调用
list-length的写法:会先对输入列表做一次完整的O(n)遍历计算长度,再执行n次循环逻辑,整体是两次线性遍历,遇到环形列表时list-length会直接陷入死循环。 - 你使用的双
for并行迭代写法:计数和列表遍历同步进行,只需要一次线性遍历就能完成全部逻辑,没有额外的长度计算开销,遇到提前退出循环的场景也不会做多余的列表遍历,性能表现更好。
未使用变量警告的解决方法
按照推荐优先级从高到低排列:
- 直接在变量位写
nil,不绑定多余变量
这是ANSI Common Lisp标准原生支持的写法,loop的for子句中变量位置传入nil时,遍历时不会创建变量绑定,从根源上避免未使用变量的问题,不需要加额外声明:(loop for i from 0 for nil in l do something) - 对未使用变量添加
ignore声明
如果你用的Lisp实现对nil作为循环变量的支持有差异,可以在循环体开头添加标准的忽略声明,所有合规Common Lisp实现都会识别该声明,不再抛出警告:(loop for i from 0 for u in l do (declare (ignore u)) something) - 使用约定的匿名变量名
包括SBCL、CCL在内的绝大多数主流Common Lisp实现,默认将单下划线_、或以下划线开头的变量名识别为“故意不使用的占位变量”,不会对这类变量抛出未使用警告,写法也比较简洁:(loop for i from 0 for _ in l do something)
选择建议
没有特殊理由的话,完全不需要改回list-length的实现方式,上述任意一种警告处理方案都符合Lisp的编码惯例,不会带来可读性或者兼容性问题。
内容的提问来源于stack exchange,提问作者Thomas Baruchel
相关产品推荐
相关产品推荐

