Loops Elisp'中的条件句;循环设施
我正试图了解Elisp的cl循环设施,但似乎找不到跳过元素的方法。这里有一个人工例子来说明这个问题:我想循环一个整数列表,得到一个新列表,其中原始列表中的所有奇数整数都是平方的。偶数整数应该省略 根据cl loop的文档,我应该能够做到:Loops Elisp'中的条件句;循环设施,loops,lisp,elisp,continue,Loops,Lisp,Elisp,Continue,我正试图了解Elisp的cl循环设施,但似乎找不到跳过元素的方法。这里有一个人工例子来说明这个问题:我想循环一个整数列表,得到一个新列表,其中原始列表中的所有奇数整数都是平方的。偶数整数应该省略 根据cl loop的文档,我应该能够做到: (loop for i in '(1 2 3) if (evenp i) append (list) else for x = (* x x) and append (list x))
(loop for i in '(1 2 3)
if (evenp i)
append (list)
else
for x = (* x x)
and append (list x))
所需的输出是”(19)
,但我得到一个错误:
cl--parse-loop-clause: Expected a `for' preposition, found (list x)
显然,和
没有按预期工作,但我不明白为什么。(我知道我可以将else块简化为只包含一个子句,这样就不再需要和
了。但是,我感兴趣的是,在这种情况下,您确实需要将多个子句与和
连接起来)
问题的第二部分:理想情况下,我能够写下:
(loop for i in '(1 2 3)
if (evenp i)
continue
for x = (* x x)
append (list x))
在其他语言中,Continue是一种非常常见的跳过迭代的方法。为什么cl循环没有continue操作符?是否有一种简单的方法可以跳过我忽略的元素(比我在第一个示例中尝试的更简单)?在Common Lisp中,不可能编写这样的循环。看 顶部有一组可变子句。但是不能在main子句的后面部分为使用类似于
的方法。因此,在IF
子句中,您不能将用于。如果要引入局部变量,则需要在顶部将其作为WITH
子句引入,然后在主体中稍后进行设置
(loop for i in '(1 2 3)
with x
if (evenp i)
append (list)
else
do (setf x (* i i))
and append (list x))
公共Lisp中的循环
也没有继续
功能。可以使用条件从句
注意,Common Lisp有一个更高级的迭代构造,作为库ITERATE
。但是,Emacs Lisp不存在该文件。您可以执行以下操作:
(loop for i in '(1 2 3)
if (oddp i) collect (* i i))
这将解决您的示例问题。这里有一个循环解决方案:
(loop for i in '(1 2 3)
when (oddp i) collect (* i i))
(delq nil
(mapcar (lambda(x) (and (oddp x) (* x x)))
'(1 2 3)))
下面是一个功能解决方案:
(loop for i in '(1 2 3)
when (oddp i) collect (* i i))
(delq nil
(mapcar (lambda(x) (and (oddp x) (* x x)))
'(1 2 3)))
这里有一个稍微不同的解决方案(小心使用mapcan
——它具有破坏性):
还有一个没有循环
(是的,我知道你要求的是循环
):
甚至没有cl-lib
(它定义了oddp
):
关于这些定义的一切都很清楚——只有Lisp。与@abo abo的例子相同
循环
是一种独立的语言。它的目的是表达常见的迭代场景,因此它可以做得很好。但Lisp不是它是一种表示迭代的领域特定语言。幸运的是,它允许您使用Lisp sexps
(想想Unixfind
命令——类似。它非常方便,但它本身就是另一种语言。)
[请不要火焰。是的,我知道dolist
和其他所有东西本质上与loop
没有什么不同——不多也不少Lisp。但是它们比loop
更为lispier。几乎任何东西都比loop
更为lispier。非常好的回答,谢谢。奇怪的是,cl loop如此强大,却让你在想要像continue这样简单的东西时跳过重重关卡。@tmalsburgloop
是支持和反对Lisp宏优点的一个例子。@Rainer--期待这一天被添加到Emacs Lisp中。@AaronMiller--你是在建议实现continue吗在循环宏的上下文中是不可能的或至少是困难的?@tmalsburg一点也不;我想说的是,虽然LOOP
是一种非常强大和灵活的语言工具,就其在通用Lisp:language中的作用而言,它也是一个非常微妙和复杂的主题,需要非常精通才能深入理解,就其在通用Lisp:language中需要自己的章节。当然,这就解决了问题。但正如我所说,这是一个人工的例子,我想了解和的用法。谢谢你的回复。谢谢你的解释。出于您提到的原因,我很惊讶地发现了loop。这似乎不习惯。我正在为emacs helm编写一个源代码,因为大多数其他源代码都使用cl loop,所以为了保持一致性,我决定遵循它。@tmalsburg:有些人非常喜欢loop
;其他人则不然。那些经常使用它的人能流利地说它的语言,并且感觉很自然。
(let ((ns ()))
(dolist (n '(1 2 3))
(unless (zerop (mod n 2)) (push (* n n) ns)))
(nreverse ns))