gpt4 book ai didi

loops - 我应该避免重置 "by hand"一个自动递增的循环变量吗?

转载 作者:行者123 更新时间:2023-12-03 09:54:36 24 4
gpt4 key购买 nike

我有一个包含几个变量的循环;其中一个在每一步递增。然而,有时,这个变量可能会被重置为 0。因此我可以写:

(loop
with z = 0
...
do (progn
(setq (z (1+ z)))
...
(if ...
(setq z 0))))

但看起来我也可以写:
(loop
for z from 1
...
do (progn
...
(if ...
(setq z 0))))

第二个版本更短(一行);但我不确定它是否真的干净;它完全符合 Lisp 标准吗?

最佳答案

我认为你应该避免这样做,有两个原因。

首先据我所见loop规范没有明确说明这是否安全,但是 dotimes 例如说

It is implementation-dependent whether dotimes establishes a new binding of var on each iteration or whether it establishes a binding for var once at the beginning and then assigns it on any subsequent iterations.



换句话说
(dotimes (i n)
... my code ...)

可能会扩展到类似
(let (...)
...
(tagbody
start
(let ((i ...))
...my code...)
(unless ... (go start))
...))

例如。

我非常强烈地怀疑 loop实现在实践中不会这样做,我认为你可能会争辩说规范暗示他们不允许这样做,但我也认为措辞不够清楚,你想依赖它。

其次我认为作为风格问题,在迭代主体内调整迭代变量的值是非常可怕的:如果有人阅读 (loop for i from 0 below 100 do ...)他们希望 i 逐步从 0 到 99 的整数,而不是因为代码中的一些隐蔽性而随机跳跃。因此,我个人会出于风格而不是确保规范允许或不说它是安全的问题来避免这种情况。

相反,我会按照 Rainer 的建议去做,即 (loop for x = ... then ...)
很明显 x具有由您的代码确定的值,而不是由 loop .

最后请注意,您可以通过例如:
> (mapcar #'funcall (loop for i below 3
collect (lambda () i)))
(3 3 3)

在这种情况下,我正在使用的实现不会,在这种情况下重新绑定(bind)它(但它可能在其他情况下当然会这样做!)。

还值得注意的是,分配给循环控制变量的可能性会阻止重要的优化成为可能:循环展开。如果系统不能假设 (loop for i from 0 to 2 do ...)评估 ...三次,与 i作为适当的值,您不能真正展开这样的循环。

关于loops - 我应该避免重置 "by hand"一个自动递增的循环变量吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59580496/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com