Lists
The name LISP stands for LISt Processing. Lists are the fundamental data structure of the language. Everything in LISP is built around lists: data, programs, and even function definitions. Understanding lists means understanding LISP.
Creating lists
With the list function
The most common way to create a list:
(list 1 2 3) ; → (1 2 3)
(list "a" "b" "c") ; → ("a" "b" "c")
(list 10.0 20.0 0.0) ; → (10.0 20.0 0.0) — a 3D point!
The elements of a list can be of different types:
(list "AutoCAD" 2025 3.14 T) ; → ("AutoCAD" 2025 3.14 T)
With the apostrophe ' (quote)
The apostrophe is a shortcut for creating lists of literal values:
'(1 2 3) ; → (1 2 3)
'("a" "b" "c") ; → ("a" "b" "c")
Warning: the apostrophe prevents evaluation. With list, arguments are evaluated:
(setq x 5)
(list x 10) ; → (5 10) — x is evaluated to 5
'(x 10) ; → (X 10) — x is NOT evaluated, it's the symbol X
Use list when your elements contain variables or expressions, and ' when you have constant values.

Accessing elements
car: the first element
(car '(1 2 3)) ; → 1
(car '("a" "b")) ; → "a"
cdr: the rest of the list (everything except the first)
(cdr '(1 2 3)) ; → (2 3)
(cdr '("a" "b")) ; → ("b")
(cdr '(1)) ; → nil (empty list)
Why car and cdr?
These names come from the architecture of the IBM 704 computer on which LISP was created in 1958. car stands for Contents of the Address Register and cdr for Contents of the Decrement Register. These names have stuck by tradition, even though nobody programs on an IBM 704 anymore!

Lawrence Livermore National Laboratory, Attribution, via Wikimedia Commons
nth: access by index
To directly access an element by its position (starting at 0):
(nth 0 '(10 20 30)) ; → 10
(nth 1 '(10 20 30)) ; → 20
(nth 2 '(10 20 30)) ; → 30
last: the last element
(last '(1 2 3)) ; → 3
length: number of elements
(length '(1 2 3)) ; → 3
(length '()) ; → 0
(length nil) ; → 0
Combinations of car and cdr
AutoLISP provides shortcuts for common combinations:
(cadr '(1 2 3)) ; → 2 — equivalent to (car (cdr '(1 2 3)))
(caddr '(1 2 3)) ; → 3 — equivalent to (car (cdr (cdr '(1 2 3))))
(cddr '(1 2 3)) ; → (3)
In CAD, these combinations are ubiquitous because points are lists of coordinates:
(setq point '(10.0 20.0 5.0))
(car point) ; → 10.0 (X coordinate)
(cadr point) ; → 20.0 (Y coordinate)
(caddr point) ; → 5.0 (Z coordinate)
Personally, I prefer using nth to access a point's coordinates — it's more immediately readable:
(nth 0 point) ; → 10.0 (X coordinate)
(nth 1 point) ; → 20.0 (Y coordinate)
(nth 2 point) ; → 5.0 (Z coordinate)
Building and modifying lists
cons: add to the beginning
cons adds an element at the head of a list:
(cons 0 '(1 2 3)) ; → (0 1 2 3)
(cons "x" '("a" "b")) ; → ("x" "a" "b")
Technically, cons creates a dotted pair — a cell that contains exactly two values. If the second argument is a list, the result is a normal list (the pair points to the rest of the chain). Otherwise, the result is a dotted pair, indicated by a dot between the two elements:
(cons 1 2) ; → (1 . 2) — dotted pair
(cons 1 '(2 3)) ; → (1 2 3) — list
The dot . is not an operator — it's how AutoLISP displays a pair whose second element is not a list. You can also write a literal dotted pair using the quoted syntax:
'(8 . "MyLayer") ; Dotted pair: key 8, value "MyLayer"
Don't confuse a dotted pair with a two-element list:
'(8 . "MyLayer") ; → (8 . "MyLayer") — dotted pair (2 values in 1 cell)
'(8 "MyLayer") ; → (8 "MyLayer") — list of 2 elements (2 chained cells)
The difference matters when using car and cdr:
;; On a dotted pair
(car '(8 . "MyLayer")) ; → 8
(cdr '(8 . "MyLayer")) ; → "MyLayer" (the value directly)
;; On a list
(car '(8 "MyLayer")) ; → 8
(cdr '(8 "MyLayer")) ; → ("MyLayer") (a list containing the value)
With a dotted pair, cdr returns the value directly. With a list, cdr returns a list. This is why dotted pairs are preferred in AutoCAD entity association lists: they allow you to extract the value with a simple cdr, without needing an additional car. We'll come back to this in the next section.
append: concatenate lists
(append '(1 2) '(3 4)) ; → (1 2 3 4)
(append '("a") '("b") '("c")) ; → ("a" "b" "c")
reverse: reverse a list
(reverse '(1 2 3)) ; → (3 2 1)
Traversing a list
With foreach
foreach is the simplest way to traverse a list:
(foreach element '("AutoCAD" "Inventor" "Revit")
(princ (strcat "\nProduct: " element))
)
Result:
Product: AutoCAD
Product: Inventor
Product: Revit

With while and cdr
The classic technique for traversing a list in LISP:
(setq mylist '(10 20 30 40 50))
(while mylist
(princ (strcat "\nElement: " (itoa (car mylist))))
(setq mylist (cdr mylist))
)
At each iteration, car extracts the first element and cdr reduces the list. When the list is empty (nil), the loop stops.
Association lists
Association lists (alists) are a very common pattern in AutoLISP. They are the LISP equivalent of a Dictionary in C#/.NET or a dict in Python: a structure that maps keys to values. Each element is a dotted pair (key . value):
(setq person
(list
(cons 0 "John")
(cons 1 35)
(cons 2 "Engineer")
)
)
;; → ((0 . "John") (1 . 35) (2 . "Engineer"))
assoc: look up by key
(assoc 0 person) ; → (0 . "John")
(assoc 1 person) ; → (1 . 35)
(assoc 9 person) ; → nil (key not found)
To get just the value:
(cdr (assoc 0 person)) ; → "John"
Association lists in AutoCAD
This is exactly the format AutoLISP uses to represent AutoCAD entities. Each entity is an association list where DXF codes serve as keys:
;; Select the last drawn entity and read its data
(setq data (entget (entlast)))
The result looks like this:
((-1 . <Entity name: ...>)
(0 . "LINE")
(10 1.0 2.0 0.0)
(11 5.0 8.0 0.0)
...)
- Code
0contains the entity type ("LINE","CIRCLE", etc.) - Code
10contains the start point - Code
11contains the end point
Practical example: analyzing a selection
(defun c:count-types (/ selection index entity entity-type counter)
(setq selection (ssget)) ; Prompt for a selection
(if selection
(progn
(setq counter '())
(setq index 0)
(repeat (sslength selection)
(setq entity (ssname selection index))
(setq entity-type (cdr (assoc 0 (entget entity))))
;; Check if this type already exists in the counter
(if (assoc entity-type counter)
(setq counter
(subst
(cons entity-type (1+ (cdr (assoc entity-type counter))))
(assoc entity-type counter)
counter
)
)
(setq counter (cons (cons entity-type 1) counter))
)
(setq index (1+ index))
)
;; Display the results
(foreach pair counter
(princ (strcat "\n" (car pair) " : " (itoa (cdr pair))))
)
)
(princ "\nNo selection.")
)
(princ)
)
This program counts entities by type in a selection. Don't worry if some functions (ssget, sslength, ssname, entget, subst, 1+) are new — the goal here is to see how association lists are used in a real-world context.
Summary
| Function | Purpose | Example |
|---|---|---|
list |
Create a list | (list 1 2 3) → (1 2 3) |
' |
Literal list | '(1 2 3) → (1 2 3) |
car |
First element | (car '(1 2 3)) → 1 |
cdr |
Rest of the list | (cdr '(1 2 3)) → (2 3) |
nth |
Element by index | (nth 1 '(1 2 3)) → 2 |
last |
Last element | (last '(1 2 3)) → 3 |
length |
Number of elements | (length '(1 2 3)) → 3 |
cons |
Add to front | (cons 0 '(1 2)) → (0 1 2) |
append |
Concatenate | (append '(1) '(2)) → (1 2) |
reverse |
Reverse | (reverse '(1 2 3)) → (3 2 1) |
foreach |
Traverse | (foreach x lst ...) |
assoc |
Look up by key | (assoc 0 alist) |
In the next chapter, we'll see how to interact with the user: asking them to click a point, enter a number or text, using AutoLISP's get* functions.
Need an AutoCAD (AutoLISP, ObjectARX, .NET, VBA) development? Contact me for a free quote.