>>1
ensure-list
Pay attention! A very useful utility function is being introduced here.
No. It's not.
(A) = A, or the other way to Lisp
Treating list of a single atom as the atom itself means that, when (atom A) => T, the following axioms hold
(car A) => A
(cdr A) => nil
(cons B A) => (B A)
(cons A nil) => A
This approach can conceptually simplify list processing, because everything becomes a list. Most list-functions would get ability to process stand alone atoms. A need for a few redundant helper entities, like unicode characters, would disappear, as they will be represented with the list itself. Lists could be entered and pretty-printed by just specifying their elements, without parentheses, required to discern single element from a list of one element. It also lowers memory consumption for lists made of cons-pairs.
Interesting feature is that Lisp's quote operator becomes replaceable by a more uniform multiargument version, meaning [A B C] could be written instead of '(A B C) and [A] instead of 'A, where [A B ... C] equals (quote A B C).
The obvious pitfall is that "(list)" results into just "list", meaning that some other way to discern symbols from funcalls has to be found. One variant is to use naming convention for function symbols - for example, starting them from lowercase letter.
Problems will arise from removal of (atom A) => T requirement. For example,
(car (car (cons (cons A B) nil)))
would result in A, instead of (A B), because of loss of structure.
Still, (car (car A)) works as expected, when (atom A) => T.
----------------------
(defun /car (x) (if (consp x) (car x) x))
(defun /cdr (x) (if (consp x) (cdr x)))
(defun /cons (x y) (cond (y (cons x y))
((consp x) (cons x nil))
(t x)))
(defun /list-rec (xs) (if xs (/cons (car xs) (/list-rec (cdr xs)))))
(defun /list (&rest xs) (/list-rec xs))
(defun /print (x)
(while x
(format t "~a " (/car x))
(setf x (/cdr x)))
(format t "~%"))