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

quote and quasiquote

How LISP's quote, quasiquote, unquote, and unquote-splicing let you treat code as inert data and selectively rebuild it as templates.

Macros & MetaprogrammingIntermediate8 min readJul 10, 2026
Analogies

Why LISP Needs Quoting

In LISP, writing (+ 1 2) at the REPL evaluates it as a function call, but sometimes you want the literal list (+ 1 2) itself as data, not its result. The special operator quote, usually written with the shorthand ', tells the evaluator 'don't evaluate this, just return it as-is.' Because LISP represents code and data with the same list structures, '(a b c) and '(+ 1 2) are both just data: lists of symbols, ready to be passed around, inspected, or later evaluated with eval.

🏏

Cricket analogy: Quoting is like a commentator reading out a scripted pre-match statement word-for-word instead of reacting live to the toss, so 'India will bat first' is reported exactly as written rather than acted upon.

quote vs quasiquote

Quasiquote (backquote, ) builds a mostly-literal template while allowing specific pieces to be evaluated: inside a backquoted form, a comma switches back to normal evaluation for just that sub-expression. So (a ,b c) produces a list whose first and third elements are the literal symbols a and c, but whose second element is the current value of the variable b. This selective evaluation is exactly what macros need to build replacement code that mixes fixed structure with caller-supplied pieces.

🏏

Cricket analogy: Quasiquote is like a templated scorecard that keeps 'Match: India vs Australia' fixed text but fills in the live run total from a variable, rather than typing the whole scorecard fresh each over.

lisp
;; quote vs quasiquote vs unquote vs unquote-splicing
(quote (+ 1 2))          ; => (+ 1 2), a list, not 3
'(a b c)                 ; => (A B C)

(let ((b 5))
  `(a ,b c))              ; => (A 5 C)

(let ((items '(1 2 3)))
  `(a ,@items b))         ; => (A 1 2 3 B)

unquote-splicing and Building Lists

,@ (unquote-splicing) goes further: instead of inserting one value in place, it splices the elements of a list variable directly into the surrounding list, flattening one level. So if items is (1 2 3), then `(a ,@items b) produces (a 1 2 3 b), not (a (1 2 3) b). This is exactly how macros like the unless example insert a caller-supplied &body, which is itself a list of forms, as a sequence of sibling forms inside progn rather than as one nested list.

🏏

Cricket analogy: Unquote-splicing is like inserting each player from a substitutes list individually into the starting XI announcement, rather than listing 'the substitutes list' as one bundled entry.

Nested quasiquotes (a backquote inside another backquote) are tricky: each comma is consumed by its nearest enclosing backquote level. If you're generating macro-writing macros, work through the nesting carefully or flatten the logic into helper functions instead.

Common Pitfalls

A common pitfall is forgetting that quoted data is inert: '(1 2 3) will never call any function even if it looks like one, so '(+ 1 2) evaluates to the three-element list (+ 1 2), not 3. The opposite mistake, forgetting to quote, is just as common: writing (list a b) when you meant (list 'a 'b) will try to evaluate a and b as variables instead of treating them as literal symbols, causing an unbound-variable error if no such variables exist.

🏏

Cricket analogy: Forgetting to quote is like a scorer reading 'six runs' off a printed placard as if it were a live update to shout, when it was only meant as a static label on the board.

Watch out: '(+ 1 2) is a three-element list of symbols and numbers, not the number 3 — quoting suppresses evaluation entirely. Conversely, (list a b) evaluates a and b as variable references; if you meant the symbols themselves, write (list 'a 'b) or `(a b).

  • quote (') prevents evaluation entirely, returning the literal list/symbol structure as data.
  • Quasiquote (`) builds a mostly-literal template; comma (,) switches back to normal evaluation for one sub-expression.
  • Unquote-splicing (,@) inserts the elements of a list directly into the surrounding list, flattening one level.
  • Quasiquote and unquote-splicing are the standard toolkit for constructing macro expansions from caller-supplied arguments.
  • Nested backquotes require care: each comma binds to its nearest enclosing backquote.
  • Forgetting to quote symbols you intend as literal data is a common source of unbound-variable errors.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#LISPStudyNotes#QuoteAndQuasiquote#Quote#Quasiquote#LISP#Needs#StudyNotes#SkillVeris#ExamPrep