List 如何在LISP中使用循环

List 如何在LISP中使用循环,list,lisp,common-lisp,List,Lisp,Common Lisp,我一直在努力理解如何在LISP中使用循环,但它们似乎仍然不能正常工作。我尝试使用以下代码: (loop for i from 0 to (list-length y) (when (eq (values-list (nth i (car y))) 0) (return-from checkZero t))) 如果我的值等于0或不等于0,则应循环检查我的列表。如果它相等,那么它应该从循环返回并退出循环,否则它应该运行,直到达到列表长度。我是否

我一直在努力理解如何在LISP中使用循环,但它们似乎仍然不能正常工作。我尝试使用以下代码:

    (loop for i from 0 to (list-length y)
          (when (eq (values-list (nth i (car y))) 0)
             (return-from checkZero t)))
如果我的值等于0或不等于0,则应循环检查我的列表。如果它相等,那么它应该从循环返回并退出循环,否则它应该运行,直到达到列表长度。我是否认为这是错误的,如果是,我如何着手修复这个循环


(我不确定我的实际代码是否有效,因为我仍在处理由错误使用的循环生成的错误,并且我找不到许多在线使用循环的好资源)

循环中的主要问题是
WHEN
-表达式。有两种方法可以编写:

  • 当条件DO forms-子句时,使用循环

    (loop for...
          when (eq ...) do (return-from ...))
    
    (loop for...
          do (when (eq ...)
               (return-from ...)))
    
  • 在循环
    DO
    -子句中使用常规
    WHEN
    -宏:

    (loop for...
          when (eq ...) do (return-from ...))
    
    (loop for...
          do (when (eq ...)
               (return-from ...)))
    
  • 您的代码中还有一些其他问题需要解决

  • 在Lisp中命名时,在单词之间使用破折号,而不是camelCase(
    checkZero
    而不是
    checkZero
  • 使用
    =
    进行一般数字比较,或使用
    ZEROP
    检查数字是否为零
    EQ
    用于检查两个对象是否为同一对象
  • 您可以使用
    return
  • 我不太确定您想用
    (VALUES-LIST(NTH…(CAR…))
    实现什么,但它不起作用。如果您试图简单地在一个简单的值列表上循环(例如
    (123456)
    ),则应该对列表中的项使用循环
  • 所以现在你应该有这样的东西:

    (defun check-zero (list)
      (loop for item in list
            when (zerop item) do (return t)))
    
    循环
    还有一个
    条件
    -子句,您可以使用:

    (defun check-zero (list)
      (loop for item in list
            thereis (zerop item)))
    
    一旦找到满足
    ZEROP
    的项,就会返回。然而,有更简单的方法来实现同样的目标。您可以使用检查列表是否包含零:

    (defun check-zero (list)
      (member 0 list :test #'=))
    
    CL-USER> (check-zero '(1 3 4 3 5 7))
    NIL
    CL-USER> (check-zero '(1 3 4 3 0 5 7))
    (0 5 7)
    
    这将返回一个广义布尔值。也就是说,在公共Lisp中,任何不是
    NIL
    的值都被认为是真的

    由于存在一个谓词函数(
    ZEROP
    )来检查对象是否为零,因此您也可以使用或
    MEMBER-if

    (some #'zerop '(1 3 4 6 2 0 45 6 7)) ;=> T
    (member-if #'zerop '(1 3 4 6 2 0 45 6 7)) ;=> (0 45 6 7)
    

    删除
    (when(eq…)(return from…)
    周围的括号,使
    when(eq…)(return from…)
    成为
    ,并在
    (return from…)
    前面加上
    do
    。有一章是关于循环的,叫做。在本书中,您有一个轻微的警告,如果要检查的列表可能合法地包含非数字,请使用
    equalp
    (如果希望0和0.0比较相等)或
    eql
    (如果希望数值和数字类型相同),因为如果参数是非数字且
    =
    可能会出错,则
    zerop
    应发出错误信号。