list - 如何在 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。如果相等则它应该返回并退出循环,否则它应该运行直到达到列表长度。我是不是在考虑这个错误?如果是,我该如何解决这个循环?

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

最佳答案

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

  1. 使用循环 WHEN 条件 DO 形式-子句:

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

    (loop for...
          do (when (eq ...)
               (return-from ...)))
    

您的代码中还有一些其他问题需要修复。

  1. 在 Lisp 中命名时,在单词之间使用破折号而不是驼峰命名法(check-zero 而不是 checkZero)。
  2. 使用 = 进行一般数字比较,或使用 ZEROP 检查数字是否为零。 EQ 用于检查两个对象是否是同一个对象。
  3. 您可以使用 RETURN
  4. 从循环中返回
  5. 我不太确定您尝试使用 (VALUES-LIST (NTH ... (CAR ...))) 来完成什么,但它不会起作用。如果您试图简单地遍历一个简单的值列表(例如 (1 2 3 4 5 6)),您应该使用循环 FOR item IN list-子句。

所以现在你应该有这样的东西:

(defun check-zero (list)
  (loop for item in list
        when (zerop item) do (return t)))

LOOP 还有一个 THEREIS 条件 - 您可以使用的子句:

(defun check-zero (list)
  (loop for item in list
        thereis (zerop item)))

一旦找到满足 ZEROP 的项目,就会返回。但是,有更简单的方法可以实现相同的目的。你可以使用 MEMBER检查列表是否包含零:

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

这将返回一个广义 bool 值。也就是说,任何不是 NIL 的值在 Common Lisp 中都被认为是真的。

因为有一个谓词函数 (ZEROP) 来检查一个对象是否为零,你也可以使用 SOMEMEMBER-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)

关于list - 如何在 LISP 中使用循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39865637/

相关文章:

c# - 从列表中获取变量列表(使用 Linq?)

recursion - 堆栈的 Lisp 递归问题

Lisp 重新创建临时变量

common-lisp - 在 Common Lisp (SBCL) 中,有没有办法检查原子的各个部分?

clojure - 包 vs 命名空间 vs 模块

r - 将列表转换为多个数据框,以便能够仅将每个数据框的一列转换为数字数据

list - J 如何制作随机数的形状

.Net 2.0 - 通用列表的效率如何?

macos - 在 Mac OS X(任何方言)上安装 lisp 的建议?

common-lisp - 在宏中构建符号时处理可读的情况