In 21 or so of LIsp coding, I've noticed that my use of car, and cadr, cadar, caddr, and all those has been greatly increasing. I hardly ever type second instead of cadr. A cursor scan of my git history confirms it.
One reason is that second and third and such are oriented toward sequences. But sequences are often generic. In TXR Lisp, I have [x 2], so why would I ever write (third x)? It's verbose, like using Roman numerals instead of Arabic.
Now if I'm processing tree structure, I know that is made of conses. So (caddr x) makes sense.
Part of the reason it makes sense is that when we are processing tree structure, such as code syntax, we cannot just evaluate (caddr x) out of the blue. We can only do that if (cddr x) has been confirmed to be a cons cell: (consp (cddr x)). The syntax could be bad. It could contain the dotted notation in an unexpected place, or be missing required arguments.
And so this makes no stylistic sense at all:
(when (and (consp x) (consp (cdr x)) (consp (cddr x))
(third x))
We want this:
(when (and (consp x) (consp (cdr x)) (consp (cddr x))
(caddr x))
It is also easier to read and verify. We know caddr is right because it just adds an
a to cddr, the last cell which was tested.
There is an impedance mismatch between validating (cddr x) and then extracting (third x), which isn't there when (caddr x) is used.
Anyway, a lot of that kind of code is avoided by pattern matching.
(when-match (@nil @nil @elem . @nil) x
elem)
That also avoids traversing the structure multiple times. Unless the compiler is clever about doing CSE between these functions, (cddr x) starts scanning at x.