3 ms·
At the end of the day, CL is an imperative language with some functional-ish features. Most CL compilers support tail recursion elimination but the CL standard
by throwaway81523 5y ago
At the end of the day, CL is an imperative language with some functional-ish features. Most CL compilers support tail recursion elimination but the CL standard doesn't require it. LOOP (subject of many amazing rants) is idiomatic. There were/are so many different mutation/update functions that SETF was developed to give them a unified API. It uses mutable arrays and CLOS objects with their setters and getters extensively. One idiomatic way to build a list is tail-first, consing onto the front, then NREVERSE the result, putting the elements into the right order by destructively reversing the pointers. The other way (done with LOOP ... COLLECTING) e.g. is to actually append using RPLACD (set-cdr! in Scheme, i.e. clobber the CDR of the last list item to make it point to a new one). You usually wouldn't do stuff like that in Haskell (look up Haskell DLists though, omg).
I'm not trying to bash CL by saying the above, but only note that it was standardized in the early 1980s to codify Lisp practices of the 1970s, an era in which memory and compute cycles were quite expensive. Programming style reflected that, using mutable variables and bit twiddling even though it was Lisp. It was before my time, and CL has never really excited me that much, though there are nice things about it.
I haven't used Clojure but it is much more modern about supporting functional data structures and idioms. If only it didn't have that Java influence...