1

这是 Common Lisp 代码:

(defun take (L)
  (if (null L) nil
     (cons (car L) (skip (cdr L)))))

(defun skip (L)
  (if (null L) nil
     (cons (car L) (take (cdr L)))))

这里的想法是,“take”将给出输入列表中的所有奇数序列元素,“skip”将给出输入列表中的所有偶数序列元素。但是,在这两种情况下都会返回整个列表。

这段代码有什么错误?这是否与 CL 处理列表的方式有关,因为 SML 中的类似代码提供了所需的输出。

fun take(lst) = 
     if lst = nil then nil 
     else hd(lst)::skip(tl(lst))
and
    skip(lst) = 
     if lst = nil then nil 
     else hd(lst)::take(tl(lst));
4

3 回答 3

4

为了解释 Sylwester 所说的,你skip在 Lisp 和 SML 中都是错误的。它应该是

(defun take (L)         ; even-indexed elements of a list L
  (if (not (null L))
     (cons (car L) (skip (cdr L)))))

(defun skip (L)         ; odd-indexed elements of a list L
  (if (not (null L))
     (take (cdr L))))

fun take(lst) = 
     if lst = nil then nil 
     else hd(lst)::skip(tl(lst))
and
    skip(lst) = 
     if lst = nil then nil 
     else take(tl(lst));
于 2013-11-23T10:55:33.970 回答
3

take和是相同的skip,所以这并不神秘。skip应该只是尾随而不是cons-ing。在这里返回的是consing。

于 2013-11-23T01:11:03.657 回答
2

值得指出的是,Common Lisp(与许多其他编程语言一样)中的索引从 0 开始,因此列表的偶数索引元素是第一个、第三个、第五个等,因为它们的索引为 0、2 , 4 等。另外值得注意的是,在 Common Lisp 中,可以取rest空列表的 ,取回空列表。(但是,你不能在每个 Lisp 中都这样做。例如,在 Scheme 中,调用cdr不是对的东西是错误的。)这意味着你可以很容易地实现 even-elements。只返回第一个元素的列表,以及列表其余部分的奇数元素。 返回列表的其余部分:odd-elementseven-elementsodd-elementseven-elements

(defun even-elements (list)
  (if (endp list) list
      (list* (first list) (odd-elements (rest list)))))

(defun odd-elements (list)
  (even-elements (rest list)))

这些行为以预期的方式运行:

CL-USER> (even-elements '(0 1 2 3 4 5))
(0 2 4)
CL-USER> (odd-elements '(0 1 2 3 4 5))
(1 3 5)

当然,如果您注意到对的调用(odd-elements x)只是对 的调用(even-elements (rest x)),我们可以even-elements按如下方式实现,并得到相同的结果:

(defun even-elements (list)
  (if (endp list) list
      (list* (first list) (even-elements (rest (rest list))))))
于 2013-11-24T04:11:14.753 回答