Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Loops Elisp'中的条件句;循环设施_Loops_Lisp_Elisp_Continue - Fatal编程技术网

Loops Elisp'中的条件句;循环设施

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

我正试图了解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))
所需的输出是
”(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

(想想Unix
find
命令——类似。它非常方便,但它本身就是另一种语言。)


[请不要火焰。是的,我知道
dolist
和其他所有东西本质上与
loop
没有什么不同——不多也不少Lisp。但是它们比
loop
更为lispier。几乎任何东西都比
loop
更为lispier。非常好的回答,谢谢。奇怪的是,cl loop如此强大,却让你在想要像continue这样简单的东西时跳过重重关卡。@tmalsburg
loop
是支持和反对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))