In terms of what they do, car and cdr are equivalent to first and rest. This is quite clear in the documentation. The HyperSpec says on the entry for first, second, &c:
The functions first, second, third, fourth, fifth, sixth, seventh,
eighth, ninth, and tenth access the first, second, third, fourth,
fifth, sixth, seventh, eighth, ninth, and tenth elements of list,
respectively. Specifically,
(first list) == (car list)
(second list) == (car (cdr list))
(third list) == (car (cddr list))
…
Notes:
first is functionally equivalent to car, second is functionally
equivalent to cadr, third is functionally equivalent to caddr, and
fourth is functionally equivalent to cadddr.
Now, there is a difference, not in functionality, but in style, when you're using these functions. This is actually called out in the HyperSpec as well, e.g., in the entry on rest:
Notes:
rest is often preferred stylistically over cdr when the argument is to
being subjectively viewed as a list rather than as a cons.
For instance, consider two ways of mapping over structures built from cons cells. In the first, we're mapping over a tree of cons cells, calling some function with each leaf (i.e., non-cons) of the tree. We check whether something is a cons with consp, and if it is, we recurse onto its car and cdr. We combine the results into a new cons cell by calling 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)))))
Alternatively, when we map over a list, we typically check for the terminal condition with endp (or null, but endp emphasizes that we're looking for the end of a list, not just looking for nil), and we call the function on the first of the list and recurse into the rest of the list. While it's pretty common to see the result constructed using cons, there's actually list* that will perform the same task when called with two arguments (in general, it can do a bit more) that emphasizes that a list is being constructed:
(defun map-over-list (function list)
(if (endp list)
'()
(list* (funcall function (first list))
(map-over-list function (rest list)))))
Either of these functions could be written using car, cdr, and cons, or with first, rest, and list*, or any combination of them, but sticking to one or the other helps people that may read the code later (including the original author), and signals the intent of the author.
And how do I eventually implement FIRST/REST using CDR, CAR?
How about:
(defun first (x) (car x))
(defun rest (x) (cdr x))
or possibly even better, if you have symbol-function:
(setf (symbol-function 'first) (symbol-function 'car))
(setf (symbol-function 'rest) (symbol-function 'cdr))
first
functions are only valid for non-empty lists (see docs.racket-lang.org/reference/pairs.html). But when it comes to Common Lisp, as your tags indicate, the specification is clear. – Protozoan