CDR,CAR和REST,FIRST和可能的实施之间的区别?

时间:2015-04-27 23:00:36

标签: list lisp common-lisp cdr

我正在学习LISP中的函数式编程,这是我遇到的问题:LISP使用CAR,CDR函数以及FIRST和REST函数。两者都与列表有关。

从我到目前为止所学到的,这两者之间存在差异,但我不太清楚它们之间的区别。

有人可以为我总结一下吗?我如何最终使用CDR,CAR实现FIRST / REST?

修改:由于已接受的答案提及文档但未链接,因此以下是CAR/CDR文档的链接,此处为FIRST/REST

此外 - 重要提示 - 链接文档是CLISP的“实施说明”,这是一种常用的环境。一般来说,几乎不可能找到这种语言的“官方文件”。

4 个答案:

答案 0 :(得分:11)

就他们的行为而言,汽车 cdr 相当于第一次休息。这在文档中非常清楚。 HyperSpec在 first second ,& c:

的条目中说明
  

第一,第二,第三,第四,第五,第六,第七,   第八,第九和第十进入第一,第二,第三,第四,   列表的第五,第六,第七,第八,第九和第十个元素,   分别。具体地,

(first list)    ==   (car list)
(second list)   ==   (car (cdr list))
(third list)    ==   (car (cddr list))
     

...

     

注意:

     

首先在功能上等同于汽车,第二是在功能上   相当于cadr,第三是功能上相当于caddr,和   第四是在功能上等同于cadddr。

现在,当您使用这些功能时, 是一个区别,而不是功能,而是 style 。这实际上也是在HyperSpec中调用的,例如,在rest上的条目中<:p>

  

注意:

     当参数为时,

休息通常优先于cdr   被主观地视为一个列表而不是一个缺点。

例如,考虑两种映射在由cons单元构建的结构上的方法。在第一个中,我们在cons单元的上进行映射,用树的每个叶子(即,非缺点)调用一些函数。我们检查某些内容是否与 consp 有关,如果是,我们会递归到 car cdr 。我们通过调用缺点将结果合并到一个新的利弊单元中。

(defun map-over-cons (function tree)
  (if (not (consp tree))
      (funcall function tree)
      (cons (map-over-cons function (car tree))
            (map-over-cons function (cdr tree)))))

或者,当我们在列表上进行映射时,我们通常会检查 endp (或 null ,但 endp >强调的终端条件我们正在寻找列表 end ,而不只是寻找 nil ),我们在列表的第一个并递归到列表的 rest 。虽然看到使用缺点构建的结果很常见,但实际上list*在使用两个参数调用时会执行相同的任务(通常,它可以做多一点)强调正在构建列表

(defun map-over-list (function list)
  (if (endp list)
      '()
      (list* (funcall function (first list))
             (map-over-list function (rest list)))))

这些功能中的任何一个都可以使用 car cdr 缺点第一个来编写, 休息列表* ,或者它们的任意组合,但坚持一个或另一个可以帮助那些可能稍后阅读代码的人(包括原作者),并发出作者意图的信号。

  

我如何最终使用CDR,CAR实现FIRST / REST?

怎么样:

(defun first (x) (car x))
(defun rest (x) (cdr x))

或者甚至可能更好,如果你有符号功能

(setf (symbol-function 'first) (symbol-function 'car))
(setf (symbol-function 'rest) (symbol-function 'cdr))

答案 1 :(得分:3)

操作firstrest表示您正在使用列表:一系列以空列表结尾的对,即它的形式(列表x1 ... xn)

操作carcdr表示您正在使用成对构建数据结构,这可能不是列表。

当您使用列表时,请选择firstrest,以便让其他人更轻松地阅读代码。

答案 2 :(得分:2)

经典,汽车和cdr更多的是机器导向,而第一次和休息是更抽象的功能。实际上,它们之间没有区别。每个人都坚持汽车和司机,所以汽车和司机都占了上风。

如果你很难找到汽车和汽车之间的任何差异,那就是因为没有。首先看一下汽车的别名。

解释

    visible_when = 'age >= 18 or last_name!="Smith"',

答案 3 :(得分:2)

首先,这些都不是谓词(或者至少,它们不是Lisp程序员所称的&#34;谓词&#34 ;;在这种情况下,&#34;谓词&#34;表示&#34; 34;一个返回布尔值的函数&#34;)。

关于这个问题,让我们快速进入一个REPL。

; SLIME 2014-12-23
CL-USER> (describe #'car)
#<FUNCTION CAR>
  [compiled function]

Lambda-list: (LIST)
Declared type: (FUNCTION (LIST) (VALUES T &OPTIONAL))
Documentation:
  Return the 1st object in a list.
Known attributes: foldable, flushable, unsafely-flushable
Source file: SYS:SRC;CODE;LIST.LISP
; No value
CL-USER> (describe #'first)
#<FUNCTION FIRST>
  [compiled function]

Lambda-list: (LIST)
Declared type: (FUNCTION (LIST) (VALUES T &OPTIONAL))
Documentation:
  Return the 1st object in a list or NIL if the list is empty.
Known attributes: foldable, flushable, unsafely-flushable
Source file: SYS:SRC;CODE;LIST.LISP
; No value
CL-USER> (describe #'cdr)
#<FUNCTION CDR>
  [compiled function]

Lambda-list: (LIST)
Declared type: (FUNCTION (LIST) (VALUES T &OPTIONAL))
Documentation:
  Return all but the first object in a list.
Known attributes: foldable, flushable, unsafely-flushable
Source file: SYS:SRC;CODE;LIST.LISP
; No value
CL-USER> (describe #'rest)
#<FUNCTION REST>
  [compiled function]

Lambda-list: (LIST)
Declared type: (FUNCTION (LIST) (VALUES T &OPTIONAL))
Documentation:
  Means the same as the cdr of a list.
Known attributes: foldable, flushable, unsafely-flushable
Source file: SYS:SRC;CODE;LIST.LISP
; No value

因此,根据文档及其签名,car相当于firstcdr相当于rest。让我们测试一下。

CL-USER> (cons 1 2)
(1 . 2)
CL-USER> (car (cons 1 2))
1
CL-USER> (first (cons 1 2))
1
CL-USER> (cdr (cons 1 2))
2
CL-USER> (rest (cons 1 2))
2
CL-USER> (cons 1 nil)
(1)
CL-USER> (car (cons 1 nil))
1
CL-USER> (first (cons 1 nil))
1
CL-USER> (cdr (cons 1 nil))
NIL
CL-USER> (rest (cons 1 nil))
NIL
CL-USER> nil
NIL
CL-USER> (car nil)
NIL
CL-USER> (first nil)
NIL
CL-USER> (cdr nil)
NIL
CL-USER> (rest nil)
NIL

所以,他们似乎是一样的。