> Not deliberately obfuscated, true. But any code that contains tokens like "CAR", "caar", "CDR", "cdar", "CONS", "caddr", etc
Do you code in Lisp? I do and I don't find it obfuscated at all. On the other hand I find it absolutely clear and beautiful.
car, caar, cdr, etc. are no more obfuscated than chmod, chown, cp, ls, etc. in shell. If you are unfamiliar with Lisp, sure they would seem obfuscated but so would those commands in shell to someone who has never done shell. But after using the shell for a while those commands become clear, concise and convenient. So do car, cdr, caar, etc. "cons" just constructs a cell. (cons "foo" "bar") constructs a cell with "foo" as its car (first element) and "bar" as its cdr (second element). It can't get simpler than that!
LISP is beautiful with terrible naming conventions, and I don't think that's a hot take. "caddr means car of the cdr of the cdr" is almost intentionally obtuse for describing the third element of a list.
> It can't get simpler than that!
It can, because in your description you introduce multiple levels of indirection.
What abomination of a syntax is that! What does [ and ] do? Why does the 2 go between the brackets? What does a[2] do? Is it making a function call? It is a statement? An expression? Or some other magic? Why deliberately create such cryptic and confusing syntax?
Why not simply (nth 2 obj) which tells clearly that this is a function call that picks the 2nd element in obj and returns it?
Seriously though, arguing about syntax to criticize a language is such a trivial and banal activity that it detracts from any useful discussion about the true merits of a language, about its expressiveness, flexibility and paradigms it supports.
Syntax is superficial (and Lisp has very little of it anyway). What syntax someone likes depends on what syntax they are familiar with. I am familiar with Lisp syntax (the very little there is of it) and C, C++, Python, Java, JavaScript, Go, Rust, APL, etc. and I find Lisp syntax the most intuitive and clear. You might find the C/Java syntax clearer and more intuitive. And that is why a discussion about syntax is superficial and pointless.
Semantics and paradigms make much better topics of discussion when talking about programming languages.
You might want indexing for linear list access. Here we have z in the dotted position of a nested list, which is tricky to connect to a simple index.
Even if we set nesting aside, our z could be in these positions:
z ;; z is the object itself
(z)
(y . z)
(y)
(x y . z)
(x y z)
and so on.
Numeric navigation of the tree structure is possible in various forms. TXR Lisp has the functions cxr and cyr which use a bitmask "address" argument to navigate the car/cdr links. The address 0 is invalid, 1 is a noop. Other than that, bit 1 means car and 0 means cdr. cxr and cyr differ in the order of the bits.
1> (cxr #b10101 '((x (y . z))))
z
I.e.
1> (cxr 21 '((x (y . z))))
z
To interpret the bitmask, we ignore the upper framing bit and follow the 0101 right to left: 1=car, 0=cdr, 1=car, 0=cdr. Of course, this just being a function argument, it can be computed. Any positive integer is a potentially valid address in some cons structure.
Indexing is supported, but doens't reach dotted positions; it is geared toward sequences, not cons structure.
2> [[['(a b (c d e (f))) 2] 3] 0]
f
That could be compressed into some kind of path mechanism where you just have the indices as 2 3 0.
The numeric address idea is inspired by the tree addressing system in Urbit's Nock. This is explained as a layer-by-layer enumeration using successive natural numbers:
1
2 3
4 5 6 7
Address is 1 is "this object". Then 2 is car, and 3 is cdr. Note that these have a binary structure 10 and 11. Similarly 4, 5, 6, 7 are 100 101 110 and 111. You can see that the bits mean 0=car 1=cdr, left to right, after skipping the framing 1 bit.
I swapped their meaning in my implementation and provided a right-to-left function.
I don't remember the exact reason I swapped the roles, but likely it was because linear lists are more common than nested lists. You do more cdr than car, loosely speaking. For instance, the simple positions in a linear list are all cdr operations followed by car: car, cadr, caddr, cadddr, ... if cdr is 0, then these look like 11, 110, 1100, 11000:
In other words, 3 is car, and then we just arithmetically left shift the 3 to get the other positions. If cdr is 1, then we have to left shift and mask in a 1 to replace the 0 that was shifted in.
Do you code in Lisp? I do and I don't find it obfuscated at all. On the other hand I find it absolutely clear and beautiful.
car, caar, cdr, etc. are no more obfuscated than chmod, chown, cp, ls, etc. in shell. If you are unfamiliar with Lisp, sure they would seem obfuscated but so would those commands in shell to someone who has never done shell. But after using the shell for a while those commands become clear, concise and convenient. So do car, cdr, caar, etc. "cons" just constructs a cell. (cons "foo" "bar") constructs a cell with "foo" as its car (first element) and "bar" as its cdr (second element). It can't get simpler than that!