![](/img/trans.png)
[英]How do lisps that prefer first and rest to car and cdr approach combinations like cdaddr?
[英]Difference between CDR, CAR and REST, FIRST and possible implementation?
我正在学习LISP中的函数式编程,这是我遇到的问题:LISP使用CAR,CDR函数以及FIRST和REST函数。 两者都与列表有关。
从我到目前为止所学到的,这两者之间存在差异,但我不太清楚它们之间的区别。
有人可以为我总结一下吗? 我如何最终使用CDR,CAR实现FIRST / REST?
编辑 :由于接受的答案提到文档,但没有链接,这里是CAR / CDR文档的链接,这里是FIRST / REST 。
此外 - 重要的说明 - 链接文档是CLISP的“实施说明”,这是一种常用的环境。 一般来说,几乎不可能找到这种语言的“官方文件”。
就他们所做的而言, 汽车和cdr相当于第一次和休息 。 这在文档中非常清楚。 HyperSpec在第一个 , 第二个和c的条目上说:
第一,第二,第三,第四,第五,第六,第七,第八,第九和第十函数分别访问列表的第一,第二,第三,第四,第五,第六,第七,第八,第九和第十元素。 特别,
(first list) == (car list) (second list) == (car (cdr list)) (third list) == (car (cddr list))
...
笔记:
第一个在功能上等同于汽车,第二个在功能上等同于cadr,第三个在功能上等同于caddr,第四个在功能上等同于cadddr。
现在, 是有区别的,而不是功能,而是在风格 ,当你使用这些功能。 这实际上也是在HyperSpec中调用的,例如,在休息条目中:
笔记:
当论证被主观地视为列表而不是缺点时,休息通常优先于风格而不是cdr。
例如,考虑两种映射在由cons单元构建的结构上的方法。 在第一个中,我们映射在cons细胞树上 ,用树的每个叶子(即,非缺点)调用一些函数。 我们检查是否有东西是consp的缺点,如果是,我们将它们递归到它的汽车和cdr上 。 我们通过调用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 ,但是endp强调我们正在寻找列表的结尾 ,而不只是查找nil ),并且我们调用函数列表的第一个并递归到列表的其余部分 。 虽然看到使用cons构造的结果是很常见的,但实际上list *将在使用两个参数调用时执行相同的任务(通常,它可以执行更多操作),强调正在构造列表 :
(defun map-over-list (function list)
(if (endp list)
'()
(list* (funcall function (first list))
(map-over-list function (rest list)))))
这些函数中的任何一个都可以使用car , cdr和cons ,或者first , rest和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))
操作first
和rest
表示您正在使用列表:一系列以空列表结尾的对,即它的形式(列表x1 ... xn)
操作car
和cdr
表示您正在使用对构建数据结构,这可能不是列表。
这是first
选择并在使用列表时rest
,以便让其他人更容易阅读代码。
传统上,汽车和cdr更多的是面向机器,而第一次和休息是更抽象的功能。 实际上,它们之间没有区别。 每个人都坚持汽车和司机,所以汽车和司机占了上风。
如果你很难找到汽车和汽车之间的任何差异,那是因为没有。 首先看一下汽车的别名。
定义?
(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
相当于first
而cdr
相当于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
所以,他们似乎是一样的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.