【问题标题】:Building a list with loops使用循环构建列表
【发布时间】:2014-11-10 23:17:30
【问题描述】:

我们今天刚刚在课堂上讨论了循环,我还有几件事需要做。简而言之,我必须使用循环而不是递归来构建一个列表。我似乎在这里遇到了绊脚石。对于这个例子,我们需要做一个简单的倒计时。该函数接受一个参数,然后返回小于或等于初始参数的所有正整数的列表。 (倒计时 5) => (5 4 3 2 1)

无论出于何种原因,我都很难获得循环。我们谈到的是 Loop、Do、Dotimes 和 Dolist。我已经用几个循环尝试了这个,并且总是得到类似的结果。

(defun countdown (num)
  (cond ((= num 0) nil)
        (T  (let* ((list nil))
              (loop
                (if (= num 0) (return list)
                    (setf list (cons list num)))
                (setf num (- num 1)))))))

我的输出显示如下:

(((((NIL . 5) . 4) . 3) . 2) .1)

更新:我已经解决了这个问题。显然我需要颠倒cons 中的顺序,所以numlist 之前。有人愿意解释一下吗?我以为您将列表放在首位,然后将您放在第二位的内容添加到列表的末尾。至少,到目前为止我是这样使用它的。

【问题讨论】:

    标签: list loops lisp common-lisp cons


    【解决方案1】:

    将参数反转为cons(以及原因)

    您在an answer 中写道(因为它要求提供更多信息,也许应该是评论):

    我已经解决了这个问题。显然我需要颠倒顺序 缺点,所以 num 在列表之前。有人愿意解释一下吗?一世 以为你把列表放在第一位,然后你放在第二位的是 添加到它的末尾。至少,到目前为止我是这样使用它的 没有问题。

    HyperSpec 中清楚地记录了该功能:Function CONS。文档中的示例显示,例如,

    (cons 1 (cons 2 (cons 3 (cons 4 nil)))) =>  (1 2 3 4)
    (cons 'a (cons 'b (cons 'c '()))) =>  (A B C)
    (cons 'a '(b c d)) =>  (A B C D)
    

    甚至是笔记

    如果 object-2 是一个列表,则可以认为 cons 生成一个新列表,它与它相似,但前面有 object-1。

    阅读14.1.2 Conses as Lists也可能会有所帮助,其中包括:

    列表是一个 conses 链,其中每个 cons 的 car 是列表的一个元素,每个 cons 的 cdr 要么是链中的下一个链接,要么是终止原子。

    关于loop

    这里的许多答案都在向您指出,循环 表单包含一种特殊的迭代语言。没错,但它也可以按照您使用它的方式使用。这种方式称为简单循环

    6.1.1.1.1 Simple Loop

    简单的循环形式是一种主体只包含化合物的形式 形式。从左到右依次评估每个表单。当。。。的时候 最后一个表格已经被评估,然后第一个表格被再次评估, 以此类推,循环往复。一个简单的循环形式建立了一个 名为 nil 的隐式块。一个简单循环的执行可以是 通过显式将控制转移到隐式块来终止 (使用 return 或 return-from)或到外部的某个退出点 块(例如,使用 throw、go 或 return-from)。

    简单的循环可能不像使用循环提供的更好功能的循环那样普遍,但如果您只是在课堂上介绍过这一点,那么您可能还没有。不过,其他答案确实提供了一些很好的例子。

    【讨论】:

      【解决方案2】:

      如果你谈到 common lisp loop,你的倒计时可能是这样的:

      (defun countdown (from-number)
        (loop :for x :from from-number :downto 1 :collect x)) 
      
      CL-USER> (countdown 10) 
      (10 9 8 7 6 5 4 3 2 1)
      

      【讨论】:

      • OP 的循环是可以的(除了 args 到 cons 是相反的)。 OP 刚刚使用了6.1.1.1.1 Simple Loop。由于“[OP] 今天在课堂上刚刚介绍了循环”,因此到目前为止,他们可能只使用了这些循环。
      【解决方案3】:

      使用loop,它有自己的“专用语言”,看起来不像 Lisp:

      (defun countdown (n)
        (loop
          for i from n downto 1
          collect i))
      

      或者使用do:

      (defun countdown (n)
        (do ((i 1 (1+ i)) 
             (res nil (cons i res)))
            ((> i n) res)))
      

      参见here,尤其是第 7 章和第 22 章。

      【讨论】:

      • OP 的循环是可以的(除了 args 到 cons 被颠倒了)。 OP 刚刚使用了6.1.1.1.1 Simple Loop。由于“[OP] 今天在课堂上刚刚涵盖了循环”,因此到目前为止,他们可能只使用了这些循环。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-25
      • 1970-01-01
      • 2017-03-24
      • 1970-01-01
      相关资源
      最近更新 更多