CDR、CAR和REST之间的差异、FIRST和可能的实现



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

从我目前所了解到的情况来看,这两者之间有区别,但我不太明白区别是什么

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


编辑:由于接受的答案提到文档,但没有链接,这里是CAR/CDR文档的链接,然后是FIRST/REST文档的链接。

此外,重要的一点是,链接文档只是CLISP的"实施说明",CLISP是一种常用的环境。一般来说,几乎不可能找到像这样的语言的"官方文件"。

就它们的功能而言,carcdr相当于firstrest。这在文档中非常清楚。HyperSpec在第一个第二个&c:

函数第一、第二、第三、第四、第五、第六、第七,第八、第九和第十访问第一、第二、第三、第四、,列表的第五、第六、第七、第八、第九和第十元素,分别地具体而言,

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

注意事项:

第一种功能等同于汽车,第二种功能等效于cadr,第三个在功能上等效于caddr,以及第四个在功能上等同于cadddr。

现在,当您使用这些函数时,的区别,不是在功能上,而是在风格上。这实际上也在HyperSpec中调用,例如,在rest:上的条目中

注意:

当论点是被主观地看作是一个列表而不是一个缺点。

例如,考虑两种映射由cons单元构建的结构的方法。在第一个例子中,我们在cons单元格的上进行映射,用树的每个叶(即非cons)调用一些函数。我们用consc检查某个东西是否是cons,如果是,我们递归到它的carcdr上。我们通过调用cons将结果组合到一个新的cons单元格中。

(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,但end强调我们正在寻找列表end,而不仅仅是寻找nil)检查终端条件,并且我们调用列表的第一个上的函数,并递归到列表的其余中。虽然使用cons构建结果是很常见的,但实际上有list*在使用两个参数调用时将执行相同的任务(通常,它可以做得更多),强调正在构建列表

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

这些函数中的任何一个都可以使用carcdrcons编写,或者使用firstrest以及list*或它们的任何组合编写,但坚持其中一个或另一个有助于以后阅读代码的人(包括原作者),并表明作者的意图

我最终如何使用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))

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

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

也就是说,当您使用列表时,请选择firstrest,以使其他人更容易阅读代码。

传统上,car和cdr更倾向于面向机器,而first和rest则是更抽象的函数。事实上,它们之间没有区别。每个人都坚持car和cdr,所以car和cd占了上风。

若你们很难找到汽车和第一辆之间的区别,那个是因为并没有区别。首先将其视为汽车的别名。

定义?

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

首先,这些都不是谓词(或者至少,它们不是Lisp程序员所说的"谓词";在本文中,"谓词"的意思是"返回布尔值的函数")。

关于这个问题,让我们跳到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

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

相关内容

  • 没有找到相关文章

最新更新