使用循环构建列表



我们今天刚刚在课堂上讨论了循环,我有一些事情需要做。简单地说,我必须使用循环而不是递归来构建列表。我似乎在这里遇到了绊脚石。对于这个例子,我们需要做一个简单的倒计时。该函数接受一个参数,然后返回小于或等于初始参数的所有正整数的列表。(倒计时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之前。有人想解释一下吗?我以为你把列表放在第一位,然后你放在第二位的内容会添加到它的末尾。至少,到目前为止,我一直在使用它,没有问题。

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

你在回答中写道(既然它要求更多信息,也许应该是一条评论):

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

HyperSpec中清楚地记录了该函数:函数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)

甚至纸币

如果对象2是一个列表,那么cons可以被认为是生成了一个新的列表,这个列表与它相似,但前面已经准备好了对象1。

这可能有助于阅读14.1.2 Conses as Lists,其中包括:

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

关于loop

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

6.1.1.1.1简单回路

一个简单的循环形式是一个主体只包含化合物的循环形式表格。从左到右依次评估每个表单。当最后一个表单已经被评估,然后第一个表单再次被评估,等等,在一个永无止境的循环中。一个简单的循环形式建立名为nil的隐式块。简单循环的执行可以是通过显式地将控制转移到隐式块而终止(使用return或return from)或到block(例如,使用throw、go或return from)。

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

如果你谈论常见的lisp循环,你的倒计时可能是这样的:

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

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

请参阅此处,特别是第7章和第22章。

相关内容

  • 没有找到相关文章

最新更新