我正试图绕过Elisp的cl-loop设施,但似乎找不到跳过元素的方法。这是一个人为的例子来说明这个问题:我想循环一个整数列表并得到一个新的列表,其中原始列表中的所有奇数整数都是平方的。偶数整数应该省略。
根据cl-loop的文档,我应该可以这样做:
(loop for i in '(1 2 3)
if (evenp i)
append (list)
else
for x = (* x x)
and append (list x))
所需的输出为'(1 9)
而我收到错误:
cl--parse-loop-clause: Expected a `for' preposition, found (list x)
显然and
没有按预期工作,但我不明白为什么。 (我知道我可以简化else块只包含一个子句,这样就不再需要and
。但是,我对你必须用{连接几个子句的情况感兴趣{1}}。)
问题的第二部分:理想情况下,我可以写下这个:
and
继续是跳过其他语言迭代的常用方法。为什么cl-loop没有continue运算符?是否有一种简单的方法可以跳过我忽略的元素(比我在第一个例子中尝试的更简单)?
答案 0 :(得分:7)
在Common Lisp中,不可能编写这样的LOOP。请参阅LOOP Syntax。
顶部有一组变量子句。但是你不能在主句中稍后使用FOR
之类的。因此,在IF
子句中,您无法使用FOR
。如果你想引入一个局部变量,那么你需要在顶部作为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))
Common Lisp中的 LOOP
也没有continue
功能。人们会使用条件句。
请注意,Common Lisp具有更高级的迭代构造作为库ITERATE
。但是Emacs Lisp并不存在。
答案 1 :(得分:3)
你可以这样做:
(loop for i in '(1 2 3)
if (oddp i) collect (* i i))
这样可以解决您的样品问题。
答案 2 :(得分:3)
这是另一个没有loop
的人(是的,我知道你要求loop
):
(let ((ns ()))
(dolist (n '(1 2 3))
(when (oddp n) (push (* n n) ns)))
(nreverse ns))
甚至没有cl-lib
(定义{{1}}):
oddp
关于这些定义的一切都很清楚 - 只需 Lisp 。与@ abo-abo的例子相同。
(let ((ns ()))
(dolist (n '(1 2 3))
(unless (zerop (mod n 2)) (push (* n n) ns)))
(nreverse ns))
是一种单独的语言。它的目的是表达常见的迭代场景,为此它可以做得很好。 但Lisp不是。 ;-)它是一种用于表达迭代的特定于域的语言。而且它可以让你使用Lisp sexps,幸运的是。
(想想Unix loop
命令 - 类似。它非常方便,但它本身就是另一种语言。)
[请不要火焰。是的,我知道find
并且所有其他内容与dolist
基本没有区别 - 不论是 Lisp 还是更少。但它们比loop
lispier 。几乎任何东西都比loop
更加轻松。]
答案 3 :(得分:2)
这是一个循环解决方案:
(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
- 这是破坏性的):
(mapcan (lambda(x) (and (oddp x) (list (* x x))))
'(1 2 3))