Introduction
Welcome back! In our previous lesson, we explored homoiconicity—the powerful Lisp concept that code and data share the same structure: the S-expression. We discussed how the Lisp interpreter works in two stages: the Reader turns text into a structured list, and the Evaluator executes that list as code. You saw that this separation is the key to Lisp's extensibility, as it allows us to manipulate code as if it were data.
Today, we're moving from the "why" to the "how." The central question is: how do we tell the Evaluator to pause and not execute an S-expression? This lesson focuses on the primary tool for that job. Your learning outcome is to use quote to prevent evaluation and treat code as data. This is the first practical step in harnessing the power of homoiconicity, and a concept you'll use constantly when writing Elisp.
1. The Default: Eager Evaluation
Let's start by reinforcing what we know. By default, the Lisp evaluator is "eager." When it sees a list, it assumes the first element is a function it must execute.
Open your *scratch* buffer in Emacs. Type the following expression and evaluate it (using C-x C-e with your cursor after the expression):
(+ 10 20)
As expected, the minibuffer shows the result 30. The evaluator saw a list, identified + as a function, evaluated the arguments 10 and 20 (which, as numbers, evaluate to themselves), and applied the function to them.
Now, what if our goal wasn't to get the sum, but to inspect the expression (+ 10 20) itself? For example, what if we wanted to extract the function symbol + from that list?
Let's try using a function you'll learn more about later, car, which returns the first element of a list. Try evaluating this:
(car (+ 10 20))
You'll get an error: wrong-type-argument listp 30.
Why? Because the evaluator follows its rules strictly. Before executing car, it first evaluates its argument, (+ 10 20). That argument evaluates to 30. The expression effectively becomes (car 30). Since 30 is a number, not a list, car fails.
We need a way to tell the evaluator: "Stop! Look at the list (+ 10 20) itself. Don't execute it."
2. quote: The "Do Not Evaluate" Command
The tool for this is a special form called quote. Its entire purpose is to prevent the evaluation of its argument, returning it exactly as written.
To see quote in action, let's watch a short, practical demonstration.
Learn Emacs Lisp in 30 Minutes
This clip from Gavin Freeborn's 'Learn Emacs Lisp in 30 Minutes' clearly demonstrates the effect of quote and introduces its common shorthand.
Watch from 07:01 to 09:34. The video explains several data types but pay close attention to the section on quote. Notice how it transforms an expression that would normally be calculated into a simple list.
As the video showed, you can write quote in two ways:
- The full form:
(quote an-expression) - The shorthand:
'an-expression
The single-quote shorthand (') is used almost universally in Lisp code. It's concise and readable. The Lisp Reader sees ' and automatically converts 'something into (quote something) before the Evaluator even sees it.
Now, let's solve our car problem from before. In your *scratch* buffer, evaluate this expression:
(car '(+ 10 20))
The result in the minibuffer is +. It worked! Here’s the step-by-step breakdown:
- The evaluator sees the expression
(car '(+ 10 20)). - It prepares to call the
carfunction, so it must first evaluate its argument,'(+ 10 20). - The
'tells the evaluator: "Do not evaluate(+ 10 20)." - The argument is therefore the literal list
(+ 10 20). - The expression becomes
(car <the-list-(+ 10 20)>). cartakes the first element of that list, which is the symbol+.
This visual summary captures the core idea perfectly.

3. Quoting Beyond Expressions: Symbols and Lists
quote is essential for handling more than just function calls. It's fundamental for working with symbols and creating lists of data.
To understand this better, let's read a short but very clear article by Protesilaos Stavrou, a well-known Emacs contributor.
Emacs Lisp Elements | Protesilaos Stavrou
This section from 'Emacs Lisp Elements' explains the distinction between a list as a function call and a list as data, highlighting the critical role of quoting.
Please read the section '6. Symbols, balanced expressions, and quoting'. Focus on the two bullet points: 'The list as a function call' and 'The list as data'. The explanation of why (car '("Protesilaos" ...)) needs a quote is particularly relevant. Also, note the discussion on self-evaluating types vs. symbols.
This reading brings up two critical points:
A. Symbols as Data
An unquoted symbol is treated as a variable, and the evaluator tries to look up its value.
Try evaluating this in your *scratch* buffer:
my-symbol
You'll get a void-variable error because my-symbol has no value. But what if you wanted to work with the symbol my-symbol itself? You quote it.
'my-symbol
This evaluates to the symbol my-symbol. It is now data. You can pass it to functions, put it in a list, and manipulate it, all because quote prevented the evaluator from trying to look up its value.
B. Self-Evaluating Types
As the article mentions, some data types don't need quoting because they evaluate to themselves. These include:
- Numbers:
42evaluates to42. - Strings:
"hello"evaluates to"hello". tandnil: The boolean values for true and false.
This is why (+ 1 2) works without quoting the numbers. The symbol + needs to be evaluated to find its function definition, but the numbers 1 and 2 evaluate to themselves.
This leads to a common pattern for creating a list of mixed data:
;; Create a list containing a number, a string, and a symbol
'(123 "my-string" another-symbol)
Without the initial quote, Elisp would try to call a function named 123, which would fail. With the quote, you get a simple list containing three data elements.
4. quote as a Special Form
You might have noticed that quote behaves differently from a regular function like + or car. A regular function always evaluates all its arguments before it runs. quote does not—in fact, its entire purpose is to not evaluate its argument.
This is because quote is not a function; it is a special form. Special forms are a small set of built-in Elisp constructs that have their own unique rules for evaluation. They provide the fundamental logic and structure of the language that functions build upon.
Let's read a formal description to solidify this distinction.
[PDF] Introduction to Lisp and Emacs
This PDF provides a more academic perspective, defining special forms and explaining precisely how quote fits into that category.
First, read section '3 Special Forms' (page 11) to understand that special forms have unique evaluation rules. Then, read section '3.3 The quote Special Form' (page 13), which describes the evaluation rule for quote as simply returning its unevaluated argument.
The key takeaway is that when the Lisp evaluator sees a list, it first checks if the first element is a special form keyword (like quote, if, let, defun). If it is, it uses the unique evaluation rule for that special form. If not, it assumes it's a regular function call and evaluates all the arguments.
Conclusion
In this lesson, you have gained control over the Lisp evaluator. By understanding and using quote, you can now cleanly separate code from data, which is the practical application of homoiconicity.
Key Takeaways:
- By default, the Lisp evaluator tries to evaluate every part of an S-expression.
- The
quotespecial form, and its shorthand', is the explicit instruction to the evaluator to prevent evaluation. quoteallows you to treat what would be executable code (like(+ 1 2)) as a simple list data structure.- It is also used to treat symbols as data, preventing the evaluator from interpreting them as variables to be looked up.
quoteis a special form, not a function, because it has unique evaluation rules—specifically, it does not evaluate its argument.
Preview of the Next Lesson:
We've established that quote is a "special form." In the next lesson, we will deepen this understanding by formally contrasting special forms with regular functions. You'll learn why this distinction is crucial for building control structures and understanding how Elisp really works. We will then continue our journey by learning about eval, the counterpart to quote, which allows you to take data and explicitly ask the evaluator to execute it as code.