Elisp的cl-loop设施中的条件

时间:2013-12-06 13:21:21

标签: loops lisp elisp continue

我正试图绕过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运算符?是否有一种简单的方法可以跳过我忽略的元素(比我在第一个例子中尝试的更简单)?

4 个答案:

答案 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))