100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

LISP Syntax and S-Expressions

How LISP's prefix-notation S-expressions work, the difference between atoms and lists, and how quoting controls evaluation.

FoundationsBeginner8 min readJul 10, 2026
Analogies

LISP Syntax and S-Expressions

LISP syntax is built entirely from S-expressions: parenthesized lists where the operator or function name comes first, followed by its arguments, a style called prefix notation. So instead of writing 2 + 3, LISP is written (+ 2 3). This may look unfamiliar at first, but the consistency pays off: every operation, from arithmetic to function calls to control flow, follows the exact same structural rule, which makes LISP's grammar unusually small and regular compared to languages with many different syntactic forms.

🏏

Cricket analogy: LISP's prefix notation, where you write (+ 2 3) instead of 2 + 3, is like how a scorer records a dismissal such as caught-behind-off-a-bowler: the action, catching or bowling, comes first, followed by who's involved, a structure that looks unusual until you're used to reading it that way.

Prefix Notation and Nested Expressions

S-expressions nest freely, and LISP always evaluates from the innermost parentheses outward. In (* (+ 1 2) (- 5 2)), the evaluator first resolves (+ 1 2) to 3 and (- 5 2) to 3, and only then multiplies those two results to get 9. There is no separate table of operator precedence to memorize, the way you need for a + b * c in infix languages, because the nesting of parentheses itself dictates the exact order of evaluation.

🏏

Cricket analogy: Evaluating the innermost expression first in a nested calculation is like calculating a batting average: you must first total the runs and count the dismissals before you can divide them to get the final average.

lisp
;; Prefix notation means the operator comes first
(+ 2 3)              ; => 5

;; Expressions nest to build more complex calculations
(* (+ 1 2) (- 5 2))  ; => 9, since (+ 1 2)=3 and (- 5 2)=3, then 3*3=9

;; Any number of arguments can follow the operator
(+ 1 2 3 4 5)        ; => 15

Atoms vs Lists

Every S-expression is either an atom or a list. An atom is an indivisible value: a number like 42, a symbol like hello, a string like a piece of text in double quotes, or a character. A list is a parenthesized sequence that groups together atoms and/or other lists, built internally from linked cons cells. This two-way split, atom versus list, is the entire grammar of LISP; there is no separate syntax for arrays, statements, or expressions the way most languages have.

🏏

Cricket analogy: An atom in LISP, like the number 42 or the symbol RUN, is like a single ball bowled: an indivisible unit of the game, while a list summarizing an over is like the ball-by-ball log of that entire over, a sequence built from those individual units.

Special Forms and Quoting

By default, evaluating a list treats its first element as a function name and applies it to the evaluated rest, which means typing (a b c) at the REPL errors unless A is actually a defined function. To stop that evaluation and treat a list as literal data, you quote it, either with the special form (quote (a b c)) or its shorthand '(a b c). Special forms such as quote, if, defun, and let are not ordinary functions at all: they follow custom evaluation rules, deciding for themselves which of their arguments get evaluated and when.

🏏

Cricket analogy: Quoting a list to stop LISP from evaluating it as a function call is like a commentator saying and that's out of the highlights reel, not live play: you're explicitly marking the data as something to display as-is, not something to execute.

lisp
;; Without quote, LISP tries to evaluate (a b c) as a function call
;; and errors because A is not a defined function.
(a b c)          ; => ERROR: undefined function A

;; With quote, the list is treated as literal data, not code
'(a b c)         ; => (A B C)
(quote (a b c))  ; => (A B C), the same thing written without shorthand

;; Special forms like IF do not evaluate all arguments normally
(if (> 5 3)
    (format t "5 is bigger~%")
    (format t "3 is bigger~%"))  ; only the taken branch is evaluated

The single-quote character is shorthand for the special form (quote ...). Special forms such as quote, if, defun, and let are handled by the LISP evaluator with custom rules for which arguments get evaluated; they are not ordinary functions, which always evaluate every argument before applying.

  • LISP syntax uses prefix notation: the operator or function name comes first inside parentheses, followed by its arguments.
  • Expressions nest freely; the innermost expressions are evaluated first, and their results feed the enclosing expression.
  • An atom is an indivisible value: a number, string, character, or symbol.
  • A list is a sequence of atoms and/or nested lists enclosed in parentheses, built from cons cells.
  • Quoting an expression with a leading quote or (quote ...) tells LISP to treat it as literal data instead of evaluating it as code.
  • Special forms like if, defun, and let are not ordinary functions; they control which of their arguments get evaluated and how.
  • Because code and quoted data share the same list syntax, understanding quoting is essential to reading and writing correct LISP.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#LISPStudyNotes#LISPSyntaxAndSExpressions#LISP#Syntax#Expressions#Prefix#StudyNotes#SkillVeris#ExamPrep