Lisp, pseudo-common
[ Modified: long ago (before 2024 Apr 13) ]
1 Lisp lists are pairs
dotted-pair notation ; dexter and abdexter ; cdr and car ; consistently half-paired ; abbr. dextral half ; contrary formation
2 List introspection in Lisp
pairs of pairs ; consistently half-paired
3 Re-listing rather than re-arranging
list of references ; duplicate memory ; extract and insert
4 Lisp and NIL: No Items in List
5 Approaches and alternatives for Common Lisp
introspective defun ; friendlier cons

Lisp is list processing (t.i. "LIS-t P-rocessing"), a means for instructing a computer for handling lists, f.e. a list of instructions.

Lisp itself is programmable, meaning its notation can be customized. In other words, Lisp is a "programmable programming language", and is partly why Lisp is said to have no syntax, unlike other computer languages.

Lisp is experienced in a interpreter program rather than with a compiler program. As such, Lisp itself can be programmed before, during, and after a computer program is written with Lisp.

A list of letters is a word, a list of words is a sentence, a list of sentences is a paragraph. Or, a paragraph is a list of sentences, a sentence is a list of words, a word is a list of letters. A number is a list of digits, a list of digits is a number.

For Lisp, text is listed within a pair of "double-quotes". A number can be prefixed with its radix, f.e. the binary #2r10000 (which is 2^4) or the hexadecimal #16r10 (which is 16^1) for the decimal 16 (which is 6 + 10^1). Alternatively, #b is #2r and #x is #16r, and decimal can be explicitly declared with #10r.


Temporarily store anything in memory by naming it with the setf, and reference or re-set that named memory any time later (An intro for Lisp with StumpWM). A list of items within parentheses ( ) is actually only a list of references to memory for each item, with no need for a name for each (Re-listing rather than re-arranging).

Constructing a list with the cons is pairing an item with another item, even when an item is already a list (Lisp lists are pairs).

An instruction is a list with the leftmost item as the name of a function. A function is defined with the defun as a named list of instructions. A list is often quoted with the quote [ or more briefly preceded by an apostrophe ] to prevent its evaluation as an instruction.

A pair of parentheses ( ) with nothing in the list is known as an "empty list". Alternatively, an empty pair of parentheses is represented by the word nil, implying nil or nothing is a list (Lisp and NIL: No Items in List).


#1 Lisp lists are pairs

1.1 Dotted-pair notation
1.2 Dexter and abdexter
1.3 Reference a half: cdr and car
1.4 Consistently half-paired lists
1.5 Abbreviated notation for the dextral half
1.6 Contrary formation and Lisp instructions

As a single item has no associates, a list of items conceptually begins when an item is paired with another (Dotted-pair notation). Written horizontally, one item is the left half and one item is the right half (Dexter and abdexter).

No need for first then last. Instead, access either half immediately (Reference a half).

Consistently pairing a new item right of a list forms a stream of half-pairs rightwardly, or when left of a list forms a stream of half-pairs leftwardly (Consistently half-paired lists).

A Lisp instruction is a list. Piece together an instruction either forwards or backwards or inside-out (Contrary formation and Lisp instructions).


#1.1 Dotted-pair notation

For Lisp, a list is constructed parenthetically one pair at a time, and notated with a space-separated-dot, t.i. a period with spacing before and after. The spacing is important because numbers can have decimal points, and Common Lisp allows a period as a character in the name of a symbol (CLHS 22.1.3.5 examples).

("A message for later." . a-lisp-symbol)

(one.symbol . 3.141592)

A parenthesis has no actual need for spacing on either side of it, neither "(" nor ")".

( ( ( ( 1 . 2 ) . 3 ) . 4 ) . 5 )

((((1 . 2). 3). 4). 5)

(5 .(4 .(3 .(2 . 1))))

#1.2 Dexter and abdexter

The cons function constructs a new list by pairing the two Lisp forms it is given, perhaps quoted (An intro for Lisp).

(cons (quote left) 'right)
  ->  (left . right)

In essence, a list is itself a single item. Therefore, lists are constructed further by pairing the next item with a prior list. As a left or right half, an item is readily referenced by its position within a sub-list, t.i. from inside to outside.

(left . right)

(L . R)

((LL . RL) . R)

(L . (LR . RR))

((LL . RL) . (LR . RR))

For example, "the left half of the right half" references the left item of a sub-list, and that sub-list is the right half of another list. That describes the position (which side of the dot) from the inside list to the outside list, with this example succintly described as the "LR".


However, multiple "l" and "r" sounds smoothly slur together ambiguously when spoken. Another term for the right side is the dexter, or adjectively as "dextral" for the dextral half. Traditionally, left of dexter is "sinister", perhaps fitting with the Scheme dialect of Lisp.

The aspiration of the "s" contrasts distinctly with the explosive "d", even for a lengthy series spoken quickly or slurred. Their blending potentially invokes a lisp when spoken quickly enough, thus giving an onomatopoeia characteristic to Lisp discussions.


Alternatively, abdexter also applies as an alternate to dexter. The "ab" prefix means "away from", f.e. abduct contrasted with adduct.

The vowel "a" of abdexter (left) pronounced with a glottal stop of the throat contrasts with the dental consonant "d" of dexter (right) at the front of the mouth. A vowel other than "a" can be chosen for supporting the consistent pronunciation of the "d" itself, regardless of personal dialect or length of series.

Therefore, "abdexter" and "dexter" provide sequences of sub-lists succinctly written and clearly spoken with either one letter or one syllable per sub-list. The written letters contrast with each other, with numbers, and with symbols on the buttonboard, either when lowercase "ad" or when uppercase "AD" or when mixed "cADr".

(abdexter . dexter)

(a . d)

((aa . da) d)

(a . (ad . dd))

((aa . da) . (ad . dd))

From inside to outside, "the left half of the right half" is the same as "the abdexter of the dexter", or the "ad" which is pronounced individually as "a-d". Visually, it is the item left of its dot within the sub-list right of its own dot.

Though a sequence of references is from inside to outside, it is readily understood from outside to inside by reading it reversely. Therefore, the prior example of "ad" also refers to the dexter (right half) of the outer list and then the abdexter (left half) of the sub-list. Dexter remains dexter, and abdexter remains abdexter, so it is the same follow-the-dot approach either way.


#1.3 Reference a half: cdr and car

For the pair of items in a list, call for its dexter reference with the cdr function, and call for its abdexter reference with the car function (An intro for Lisp).

(cdr '(a . d))
  ->  D

(car '(a . d))
  ->  A

Chaining multiple references accesses a list initially from its outside then gradually towards its inside.

    (car (car '((aa . da) . d)))
==  (car '(aa . da))
      ->  AA

    (cdr (car '((aa . da) . d)))
==  (cdr '(aa . da))
      ->  DA

Multiple car and cdr references can be consolidated by functions named with the concise sequences. Common Lisp provides functions for up to four places, f.e. cddddr. It is a bit like simply removing the "r(c" of consecutive functions, and their corresponding ")".

    (car(cdr '((aa . da) . (ad . dd))))
==  (cadr '((aa . da) . (ad . dd)))

The resulting inside-out sequence of references from the abdextrally half-paired Lisp instructions is least to greatest. This is in contrast to the greatest to least approach with digits in numbers (Pairs of pairs accessed sequentially).


#1.4 Consistently half-paired lists

Besides the purposful construction of a list, there are a couple of obvious approaches for consistently constructing a list of arbitrary content.

((((1 . 2). 3). 4). 5)

(5 .(4 .(3 .(2 . 1))))

Consistently pairing a new item right of a list forms a stream of half-pairs dextrally, ensuring the final item added is readily accessible with merely the cdr function.

   (1    . 2   )
   (a    . d   )

  ((1    . 2   ). 3  )
  ((aa   . da  ). d  )

 (((1    . 2   ). 3  ). 4 )
 (((aaa  . daa ). da ). d )

((((1    . 2   ). 3  ). 4 ). 5)
((((aaaa . daaa). daa). da). d)

Consistently pairing a new item left of a list forms a stream of half-pairs abdextrally, meaning the final item added is readily accessible with the car function instead.

               (2    . 1)
               (a    . d)

         (3   .(2    . 1 ))
         (a   .(ad   . dd))

    (4  .(3   .(2    . 1  )))
    (a  .(ad  .(add  . ddd)))

(5 .(4  .(3   .(2    . 1   ))))
(a .(ad .(add .(addd . dddd))))

A half-paired list of n items bypasses most its potential of 2^(n-1) items. For example, a 10 item half-paired list has 9 pairings wherewith it has 2^9 or 512 total possible positions. However, its other 502 locations are open for potential expansion.

Perhaps meaningfully pair each current item with an additional shorter half-paired stream or a chunk of pairs of pairs. Similarly for the 256 potential positions in the other half, perhaps as complementary information.


#1.5 Abbreviated notation for the dextral half

A space separated dot before a parenthetical list, t.i. the dextral half, can be abbreviated by removing both that prior dot and the parentheses for that next list. Notably, the Lisp interpreter favors this abbreviation for the dextral half, such as in abdextrally half-paired lists, when printing Lisp forms in messages.

    (a .(ad .(add .(addd . dddd))))
==  (a   ad .(add .(addd . dddd)))
==  (a   ad   add .(addd . dddd))
==  (a   ad   add   addd . dddd)

Or:
    (a .(ad .(add .(addd . dddd))))
==  (a .(ad .(add   addd . dddd )))
==  (a .(ad   add   addd . dddd  ))
==  (a   ad   add   addd . dddd   )

One way of reversing that abbreviated notation is by pairing items from left to right, t.i. explicit dotted-pair notation of the car with the cdr.

    (a ad add addd . dddd)
==  (a .(ad add addd . dddd))
==  (a .(ad .(add addd . dddd)))
==  (a .(ad .(add .(addd . dddd))))

In other words, two items in a list without a dot between them means everything on the right half is actually another list. A Lisp list is truly a pair.


A list with nil as its dextral half, an empty list (Lisp and NIL), has only its abdextral half to show for itself.

    (a . nil)
==  (a .())
==  (a)

    (a ad . nil)
==  (a ad .())
==  (a ad)
==  (a .(ad))
==  (a .(ad .()))
==  (a .(ad . nil))

#1.6 Contrary formation and Lisp instructions

A Lisp function is used in an abdextrally half-paired list with the function name conveniently as the outermost abdexter. This also fits well with typing text from left-to-right, but that is contrary to the natural leftward formation of abdextrally half-paired lists.

(setf abbi-list (cons 3 nil))
  ->  (3)

(setf abbi-list (cons 2 abbi-list))
  ->  (2 3)

(setf abbi-list (cons 1 abbi-list))
  ->  (1 2 3)

(setf abbi-list (cons '+ abbi-list))
  ->  (+ 1 2 3)

(eval abbi-list)
  ->  6

abbi-list
  ->  (+ 1 2 3)

Contrary formation either dextrally or abdextrally is simple with setf (An intro for Lisp) by pairing the new content with the innermost item.

(setf dex-list '((2 . 3). 4))
  ->  ((2 . 3). 4)

(setf (caar dex-list)
 (cons 1 (caar dex-list)))
  ->  (1 . 2)

dex-list
  ->  (((1 . 2). 3). 4)

A list as a Lisp instruction, such as for a Lisp function, is an abdextrally half-paired list that started with nil as its dextral half. That nil is the innermost item of the list. Simply substitute it with a pairing of the desired content and nil for maintaining that integrity.

(setf do-it-later
 (quote (setf one 1 . nil)))
  ->  (SETF ONE 1)

(setf (cdddr do-it-later)
 (cons 'two nil))
  -> (TWO)

do-it-later
  ->  (SETF ONE 1 TWO)

(setf (cddddr do-it-later)
 (cons 2 nil))
  -> (2)

do-it-later
  ->  (SETF ONE 1 TWO 2)

(setf (cdr (cddddr do-it-later))
  (cons 'three (cons 3 nil)))
   -> (three 3)

do-it-later
  ->  (SETF ONE 1 TWO 2 THREE 3)
  ==  (SETF ONE 1 TWO 2 THREE 3 . nil)

Unwinding an abdextrally half-paired list (Exploring a half-paired list) exposes the middle items, and eventually the innermost item.

(setf later.too (quote (setf one 1 . nil)))
  ->  (SETF ONE 1)

(setf later.too
 (cons
  (cons (cADr later.too) (cAr later.too))
  (cDDr later.too)))
  ->  ((ONE . SETF) 1)

  Once more...
  ->  ((1 ONE . SETF))

(setf (car later.too)
 (cons 'two (car later.too)))
  ->  (TWO 1 ONE . SETF)
later.too
  -> ((TWO 1 ONE . SETF))

(setf (cdr later.too)
 '(2 three 3 . nil))
  ->  (2 THREE 3)
later.too
  ->  ((TWO 1 ONE . SETF) 2 THREE 3)

(setf later.too
 (cons
  (cDAr later.too)
  (cons (cAAr later.too) (cDr later.too))))
  ->  ((1 ONE . SETF) TWO 2 THREE 3)

  Twice more...
  ->  (SETF ONE 1 TWO 2 THREE 3)

#2 List introspection in Lisp

2.1 Pairs of pairs accessed sequentially
2.2 Exploring a half-paired list

A Lisp list is constructed as a pair with cons, and the car and cdr reference its left and right halves (Lisp lists are pairs). This provides an opportunity for pairs of pairs, as well as sequentially formed (t.i. half-paired) lists either abdextrally or dextrally.

Multiple pairs of pairs exponentially increase the potential storage of items: 2 from one pair, 2*2 from two, 2*2*2 from three, 2*2*2*2 from four, and so forth. Therein, an item is efficiently accessed by halving.

Positionally reference one half the list, either left or right, for each pairing: once for any item of 2, twice for any item of 2*2, thrice for any item of 2*2*2, and so forth.

Abbreviated functions consolidate two, three, or four car and cdr references, f.e. cadddr or cddddr. Access any of 2^4 or 16 halves with a single function, or any of 2^(4+4) or 256 items with two functions, or any of 2^(4+4+4) or 4096 with three functions, and so forth.


#2.1 Pairs of pairs accessed sequentially

A pair is 2 items, a pair of pairs is 4 items, a pair of pairs of pairs is 8 items, and so forth exponentially. An item in an exponentially paired list is referenced by gradually halving the list towards its position and noting each half leading to it.

The sequence of bisecting directions from outside to inside is also a binary description, thereby a binary number for each item. Assigning "left" as 0 and "right" as 1 reveals the sequence of binary digits for each item.


However, the abdextrally half-pairing of Lisp instructions leads to an inside-out consolidated reference. The binary digits are reversed as least to greatest for each number. This has no effect for percieving the sequence, only for interpreting the number.

Paired once:   2^1 = 2 items
   car  cdr
   (a  . d)
    0    1

Paired twice:  2^2 = 4 items
  caar  cdar    cadr  cddr
 ((aa  . da)  . (ad  . dd))
   00    10      01    11
   0     1       2     3

Paired thrice: 2^3 = 8 items
  caaar cdaar   cadar cddar     caadr cdadr   caddr cdddr
(((aaa . daa) . (ada . dda)) . ((aad . dad) . (add . ddd)))
   000   100     010   110       001   101     011   111
   0     1       2     3         4     5       6     7

The numbers sequentially increase from left to right starting from zero, the equivalent of the rightward displacement of each item from the left end. The first item from the left has 0 items before it so skip zero items, the second item from the left has 1 item before it so skip one item, and so forth.

Therefore, the consecutive references with car and cdr describing the traversal from inside to outside for an item is equivalently the reversed binary digits for the rightward displacement of an item.


Access an item by noting its perceived sequential displacement as a reversed binary number. It has the same number of digits as the number of times an item is paired within the list, or the number of parentheses at the beginning or ending of the list.

For example, each item in a list of 16 items is paired four times (2 * 2 * 2 * 2 = 16), so consider the binary number for a position as four digits. The sixth item is displaced by 5 others, 5 is #b0101, reversed is 1010: use cDADAr.

Recall, only one function is needed for referencing any of 16 halves, two functions for any of 2^(4+4) or 256, three for any of 2^(4+4+4) or 4096, and so forth. For example, the cDAAr of the cDADAr is the 42nd item of 128 (t.i. 2^7), but so is the cDAADr of cADAr, because it is the "daadada". (But, within 64 items the 42nd is only "daadad".)


Consider using the Lisp interpreter for revealing binary numbers. The format (CLHS) prints a number as binary with ~b (CLHS 22.3.2.3). Or, also give the number of desired digits and a zero (preceded by an apostrophe ') (CLHS 22.3.2.1) for padding empty places. Then use the reverse (CLHS).

(format nil "~b" 41)
  ->  "101001"
(format nil "~7b" 41)
  ->  " 101001"
(format nil "~7,'0b" 41)
  ->  "0101001"

(reverse (format nil "~7,'0b" 41))
  ->  "1001010"
Hence:
       daadada

#2.2 Exploring a half-paired list

2.2.1 Dexi-abbi introspection
2.2.2 Abbi-abbi introspection

A half-paired list is a singular item paired with another list, perhaps by first pairing with an empty list, t.i. nil. Access the singular item of an abdextrally half-paired list with car, or of a dextrally half-paired list with cdr.

A consistently half-paired list is continuously deconstructable by referencing its inner list, with cdr for an abdextrally half-paired list or car for an dextrally half-paired list. Setting aside the singular items by constructing a new half-paired list opportunes reconstruction of the original list.

(setf
 dexi nil
 abbi '(1 .(2 .(3 .(4 . nil)))))

Dextrally cons             De-cons the
a half-paired list.        abdextrally half-paired list.

(cons dexi (car abbi))     (cdr abbi)

             (nil . 1)     (2 .(3 .(4 . nil)))
                    |       |
                   cdr     car

The foremost item of the inspected half-paired list is set aside as the former middle item. The inspected half-paired list is then deconstructed to its inner list, thereby exposing the next middle item.

Gradual unwinding exposes the middle items of the inspected list consistently with cdr or car from either replacement list. Pairing both lists into a new list would maintain that point of introspection. The order of the pairing is only a matter of preference because both halves are equally accessible.


#2.2.1 Dexi-abbi introspection.

Consider constructing dextrally half-paired lists from items of an abdextrally half-paired list while deconstructing it. Forming the dextrally half-paired list in the abdextral half maintains the visual appearance of the sequence order when printed.

(setf coil '(1 .(2 .(3 . 4))))

  ->  (1 2 3 . 4)

Introspection:
  (setf coil
   (cons
    (cons (cAr coil) (cADr coil))
    (cDDr coil)))

                      cADr
                       |
              (1     .(2 .(3 . 4)))
                       |
  ->         ((1 . 2).(3 . 4))
                   |
  ->    (((1 . 2). 3).     4)
                   |
                  cDAr

  Reversal:
    (setf coil
     (cons
      (cAAr coil)
      (cons (cDAr coil) (cDr coil))))

                                 Default Lisp printer:

        (((1 . 2). 3). 4)    ==  (((1 . 2) . 3) . 4)
    ->   ((1 . 2).(3 . 4))   ==  ((1 . 2) 3 . 4)
    ->    (1 .(2 .(3 . 4)))  ==  (1 2 3 . 4)

#2.2.2 Abbi-abbi introspection.

A Lisp instruction is an abdextrally half-paired list that began with nil (Contrary formation and Lisp instructions). The Lisp printer favors the abbreviation for when a list is the dextral half of a pair (Abbreviated notation for a dextral half).

Consider constructing abdextrally half-paired lists from items of another abdextrally half-paired list (f.e. a Lisp instruction) while deconstructing it. A pair of abdextrally half-paired lists is printed more compactly than with a dextrally half-paired list (Dexi-abbi introspection).

(setf abbi-abbi
 (cons nil '(1 2 3 4 . nil)))

->  (NIL 1 2 3 4)

Introspection:
  (setf abbi-abbi
   (cons
    (cons (cADr abbi-abbi) (cAr abbi-abbi))
    (cDDr abbi-abbi)))

     cAAr              cADr                  Lisp printer:
      |                 |
       (nil          . (1 2 3 4 . nil))  ==  (NIL 1 2 3 4)
->  ((1 . nil)       . (2 3 4 . nil))    ==  ((1) 2 3 4)
->  ((2 1 . nil)     . (3 4 . nil))      ==  ((2 1) 3 4)
->  ((3 2 1 . nil)   . (4 . nil))        ==  ((3 2 1) 4)
->  ((4 3 2 1 . nil) .    nil)           ==  ((4 3 2 1))

Reversal:
  (setf abbi-abbi
   (cons
    (cDAr abbi-abbi)
    (cons (cAAr abbi-abbi) (cDr abbi-abbi))))

Of course, there was no need for prepending nil other than for slightly more compact printing. Without it, the reversal of the introspection results in the original abdextrally half-paired list without further ado.

Alternatively, reversal of an abbi-abbi introspection is as convenient as re-pairing the cdr with the car, then using the exact same introspection. Afterwards, the original first item is the cdr, so re-pair them once again.

(setf abbi-abbi
 (cons (cdr abbi-abbi) (car abbi-abbi)))


[ ...describe using introspection for gradually constructing a Lisp form (which is an abdextrally half-paired list that began with nil). Also consider revising the examples in StumpWM section, promoting defining buttons for introspecting forwards and backwards, which now makes it easier to append to the innermost contrary position of a half-paired list (Contrary formation and Lisp instructions) with just cdr after unwinding the list all the way to nil... ]


[ ...

Consider associating each instruction to a button on the buttonboard (Introspect a referenced half-paired list), one for the next list item and one for the prior list item. Associate the placeholder name to another list for modifying it with introspection (Re-listing rather than re-arranging). Afterwards, rewind it completely and then set the placeholder name to nil to detach the association.

Consider copy-list or copy-tree.


... ]

[ ...describe including the nifty (+ 1(length(car coil.my))) for position of introspected item for each evaluation by means of each defined key. For example, consider the cons for pairing the introspected item (as dexter) with its position for evaluation with stumpwm:eval-line, like when introspecting keysyms for keycodes listing (but that would be without the plus one because the keycodes were matched with the default zero indexing of arrays)... ]


#3 Re-listing rather than re-arranging

[ ...list of references... ]
[ ...duplicate memory... ]
3.3 [ ...extract and insert... ]

[ ...need to revise...
...trying to get across the notion of referencing memory
 and clarify how to ensure duplication when desired...

...referring to something in memory actually means
 referring to the memory itself...

...changing what is in the memory means
 whatever referred to the memory
 also refers to whatever happened to the memory...

...working on a copy
 requires duplicating what is in memory
 rather than referencing the memory...

...named memory is a reference to memory...
...car and cdr reference memory...

...using format
 with named memory results in "double-quoted text"...
...using read-from-string
 with "double-quoted text" results in a Lisp form...
...combining both results in a duplication of named memory...

...inserting text into a prompt is new or duplicated,
 f.e. invoking copy-last-message
 then invoking a prompt
 then using "Control-y"...

... ]

Realize the difference between a list of items and the items themselves, for it is the same difference between a grocery list and the groceries themselves. Similarly, the cdr and car call forth the references from a list, each a reference to memory for an item.

The cons constructs a new list, and the setf replaces a reference at a position in a list with another rather than modifying the content (An intro for Lisp with StumpWM). List items are never moved, neither within a list nor from one list to another, but instead a new list of references is made in the preferred order, thereby the same memory.

The Lisp interpreter uses the content of memory (an item), and also conveniently prints a copy of the actual item rather than the memory address. However, that obscures whether a placeholder name has the original or only a reference.

Consider preventing ambiguity by naming a placeholder with intent when using setf.

(setf list.1 '(one two three four))
  ->  (ONE TWO THREE FOUR)
(setf part.1 (cdr list.1))
  ->  (TWO THREE FOUR)
(setf part.1.ref (cdr list.1))
  ->  (TWO THREE FOUR)

(cadr list.1)
  ->  TWO
(setf (cadr list.1) 'five)
  ->  FIVE

(cadr part.1)
  ->  THREE
(setf (cadr part.1) 'six)
  ->  SIX

(caddr part.1.ref)
  ->  FOUR
(setf (caddr part.1.ref) 'seven)
  ->  SEVEN

list.1
  ->  (ONE FIVE SIX SEVEN)
part.1
  ->  (FIVE SIX SEVEN)
part.1.ref
  ->  (FIVE SIX SEVEN)


;; Consing references.
(setf list.2 (cons list.1 part.1.ref))
  ->  ((ONE FIVE SIX SEVEN) FIVE SIX SEVEN)

;; Setting placeholder.
(setf part.1.ref 'eight)
  ->  EIGHT

;; Changing reference.
(setf (cdr part.1) 'nine)
  ->  NINE

list.1
  ->  (ONE FIVE . NINE)
part.1
  ->  (FIVE . NINE)
part.1.ref
  ->  EIGHT

;; No surprise, maybe.
list.2
  ->  ((ONE FIVE . NINE) FIVE . NINE)

The format (CLHS) results in "double-quoted text", and the read-from-string (CLHS) results in a Lisp form from reading "double-quoted text". Combine both in order to duplicate any Lisp form, such as from named memory.

(setf thing.1 '(cons a d))
  ->  (CONS A D)

(setf thing.2
 (read-from-string
  (format nil "~s"
   thing.1)))
  ->  (CONS A D)

(setf thing.3
 (read-from-string
  (format nil "'(~s~s)"
   thing.1 thing.2)))
  ->  ((CONS A D) (CONS A D))

[ ...

Consider copy-list (CLHS) to copy the structure of a list without copying the content. Consider copy-tree (CLHS) for a list of pairs of pairs. Consider copy-seq (CLHS). Consider concatenate (CLHS) for an actual copy.
... ]


#3.3 [ ...extract and insert... ]

...extract the cADr from abbi-abbi introspection, by reference (Abbi-abbi introspection)...

(setf abbi.extracted
 (cons
  (cADr abbi.inspect)
  abbi.extracted))

(setf (cdr abbi.inspect)
 (cddr abbi.inspect))

...insert an extracted item as the cADr for abbi-abbi introspection, by reference...
...t.i. pair the extracted item with the cDr of the list...

(setf (cdr abbi.inspect)
 (cons
  (car abbi.extracted)
  (cDr abbi.inspect)))

(setf abbi.extracted
 (cdr abbi.extracted))

...name leftward introspection as "abbi<", rightward as "abbi>", and display the list with "abbi.inspect"...
...combine introspection by either "abbi<" or "abbi>" with the "abbi.inspect" for displaying the list as result after shifting the list,
then the cdr can ensure only the list is shown, t.i. without the partial list that is returned when shifting...

(cdr
 (cons
  (eval abbi>)  abbi.inspect))

(cdr
 (cons
  (eval abbi.extract)  abbi.inspect))

#4 Lisp and NIL: No Items in List

Embracing items with parentheses
 acknowledges those items
 are associated with each other.

Nil is an empty list,
 as in "nothing in list".
 But that also asserts "Nil Is a List"
 rather than nothingness itself.
 It has become the mnemonic name
 for an empty set of parentheses.

   nil  ==  ()
        ==  '()  ; quoted Lisp form


A list of one item
 is never notated as a list,
 t.i. it has no parentheses.
 It is written simply as the item itself,
 for there are no other items associated.

A list of more than one item
 is notated as a dotted list,
 with a spaced separated period
 before its final item.

   '(one two . three)


A list with nil as its final item
 is commonly abbreviated
 without dotting with nil.

   '(one . nil)  ==  '(one)


A list of items without
 a dotted final item
 has visually consistent
 delimitation, thereby
 is a "proper list".
But as a list without
 a dotted final item,
 a proper list is merely
 the abbreviated form
 for its items dotted with nil
 as the final item.

   '(one)  ==  '(one . nil)


As such, a proper list with only nil
 is a list with an empty list:

   '(nil)  ==  '(())

 but is also the abbreviated form
 for a list of items dotted with nil
 as its final item:

   '(nil)  ==  '(nil . nil)

 which is a dotted list of two lists,
 or the egregious enlightenment emoticon
 for "I am become nil":

   '(nil)  ==  '(() . ())


--------


Consing constructs a dotted list.

   (cons 'one 'two)
     ->  '(one . two)


Multiple consing results in
 the last item added
 becoming the first.

   (cons 'three       ; second cons
    (cons 'one 'two)) ; first cons
      ->  '(three one . two)


Consing an item with nil
 results in a proper list,
 because a proper list
 is the abbreviated form
 for its items dotted with nil
 as its final item.

   (cons 'three            ; third cons
    (cons 'two             ; second cons
     (cons 'one nil)))     ; first cons
       ->  '(three two one . nil)
       ==  '(three two one . ())
       ==  '(three two one)


A proper list beginning with nil
 begins and ends with a list.

   (cons nil '(one))
     ->  '(nil one)
     ==  '(nil one . nil)
     ==  '(()  one .  ())

#5 Approaches and alternatives for Common Lisp

5.1 An introspective approach for defun
5.2 A friendlier cons

It seems like introspection of computer processing has always been ignored by computer programmers and hardware manufacturers. Nothing made explorable, or exploration of instructions written personally is buried within what was supplied by default.

The SBCL interpreter seems about as unfriendly with its feedback as any other Lisp or shell interpreter or computer program compiler. The "restarts" and whatnot of Common Lisp seem almost completely unusable and unreliable when compared to the pause/continue/step half-baked approaches of other systems.

Despite such disheartening contrary interests, Lisp interpreters tend to be personalizable. Changes can be made, for the moment or for longer.


#5.1 An introspective approach for defun

According to the description for defun (CLHS), there seems to be no access to the definition of a Lisp function from its results.

In particular, defun does not make the function definition available at compile time. An implementation may choose to store information about the function for the purposes of compile-time error-checking (such as checking the number of arguments on calls), or to enable the function to be expanded inline.

Consider constructing the replacement for a function with setf and the same name as that function (Assigning to named memory from collections). The instruction can be modified later and re-evaluated to replace again.

Describe Function: stumpwm::print-key
function: print-key
(print-key key)
Eval: stumpwm::print-key
The variable STUMPWM::PRINT-KEY is unbound.Backtrace...
Eval: (setf stumpwm::print-key '(defun stumpwm::print-key ...yadda yadda yadda...))
Eval: (eval stumpwm::print-key)
STUMPWM::PRINT-KEY

Consider pairing the original definition of the function with the replacement, for restoring either one as neeeded.

Eval: (setf stumpwm::print-key (cons stumpwm::print-key nil))
Eval: (setf stumpwm::print-key (cons '(defun stumpwm::print-key ...yoda yoda yoda...) stumpwm::print-key))

Consider pairing a description with each version to identify which is the replacement.

Eval: (setf (car stumpwm::print-key) (cons "original" (car stumpwm::print-key)))
Eval: (setf (cdr stumpwm::print-key) (cons "replacement" (cdr stumpwm::print-key)))


[ ...describe
 (or revise and reference section
 Reading and writing to external memory)
 about writing to external storage for later re-use
... ]

#5.2 A friendlier cons

The cons (CLHS) constructs a list of two items (Dexter and abdexter) regardless of whether either item is nil (Lisp and NIL), yet it requires both items are specified. Consider making both items optional, wherewith each item defaults to nil.


The COMMON-LISP package might be locked by default in SBCL (SBCL 12.1.1 Package Locks). Consider temporarily unlocking it with sb-ext:unlock-package (SBCL 12.2) in order to redefine the cons name with defun (CLHS), or pick a different name than "cons".

Eval: (defun cons (&optional Fabdexter Fdexter) (cl:cons Fabdexter Fdexter))
Lock on package COMMON-LISP violated when setting fdefinition of CONS
     while in package STUMPWM-USER.
See also:
  The SBCL Manual, Node "Package Locks"
  The ANSI Standard, Section 11.1.2.1.2Backtrace for: #<SB-THREAD:THREAD "main thread" RUNNING {0123456789}>
0: (STUMPWM::BACKTRACE-STRING)
...
Eval: (sb-ext:unlock-package 'cl)
T
Eval: (defun cons (&optional Fabdexter Fdexter) (cl:cons Fabdexter Fdexter))
CONS
Eval: (sb-ext:lock-package 'cl)
T

Beginning the construction of an abdextrally half-paired list with nil for a Lisp instruction matches with the abbreviated results themselves. No more typing for nothing.

(setf abbi-list (cons 3))
  ->  (3)
  ==  (3 . NIL)

(cons)
  ->  (NIL)
  ==  (NIL .())
  ==  (NIL . NIL)

sharing