Programming

Difference between set setq and setf in Common Lisp

27 September 2026 · 9 min read

Difference between set setq and setf in Common Lisp

Understanding the subtle yet crucial difference between set, setq, and setf in Common Lisp is fundamental for any Lisp programmer. These three assignment operators are workhorses in Lisp code, but using them interchangeably can lead to unexpected behavior and debugging headaches. While they all ultimately assign values, their mechanisms and use cases differ significantly. Mastering these distinctions allows you to write cleaner, more efficient, and more robust Common Lisp programs. This guide will delve into the nuances of each operator, providing examples and practical scenarios to illuminate their proper usage. We will explore the historical context, their evolution, and the reasons why Common Lisp provides these seemingly redundant tools. By the end of this article, you’ll have a firm grasp on when and how to use each operator effectively.

Delving into set: The Grandfather of Assignment

set is the most basic assignment operator in Common Lisp. It takes two arguments: a symbol and a value. The symbol is treated as a literal name, and the value is assigned to the value cell associated with that symbol in the current dynamic environment. This means that set is primarily used to assign values to global variables or dynamically bound variables. One crucial aspect of set is that it does not evaluate its first argument. The symbol is taken literally, which can sometimes lead to errors if you intend to evaluate an expression that results in a symbol.

For example, if you have a variable x bound to the symbol y, and you try to use set like this: (set x 10), you are not assigning the value 10 to the variable y. Instead, you are trying to assign the value 10 to a symbol whose name is the value of x. This behavior can be confusing, especially for programmers coming from other languages where assignment operators typically evaluate both sides. Due to this quirk, set is generally less frequently used than setq and setf in modern Common Lisp programming.

Consider this scenario: you want to update a configuration setting that is stored in a global variable. You might use set for this purpose, ensuring that the variable is properly assigned the new configuration value. However, using setq is often a safer and more readable alternative, especially when dealing with simple variable assignments. Always double-check the context to ensure you’re assigning to the correct symbol. As Paul Graham notes in ANSI Common Lisp, understanding these subtle differences is key to writing idiomatic Lisp [^1].

setq: The User-Friendly Assignment Operator

setq is arguably the most commonly used assignment operator in Common Lisp. It stands for “set quoted,” and it addresses the primary inconvenience of set: the need to explicitly quote the symbol being assigned to. setq implicitly quotes its first argument, making it much more convenient for assigning values to variables. This simplifies the syntax and reduces the likelihood of errors caused by forgetting to quote the symbol.

Instead of writing (set ‘x 10), you can simply write (setq x 10) with setq. The result is the same: the variable x is assigned the value 10. However, the latter is much more readable and less prone to errors. setq can also take multiple pairs of symbols and values, allowing you to assign multiple variables in a single expression. For example, (setq x 10 y 20 z 30) assigns 10 to x, 20 to y, and 30 to z in one go. This makes setq a very efficient and convenient tool for initializing or updating multiple variables simultaneously.

Featured Snippet: The main difference between set and setq lies in how they handle their first argument. set expects a symbol as its first argument, which is not evaluated. setq, on the other hand, implicitly quotes its first argument, treating it as a symbol without requiring explicit quoting. This makes setq much more convenient and less error-prone for assigning values to variables in most common scenarios.

setf: The General-Purpose Assignment Operator

setf is the most versatile and powerful assignment operator in Common Lisp. It is a generalized assignment operator, meaning that it can be used to assign values to a wide variety of locations, not just simple variables. setf can handle assigning values to elements of arrays, fields of structures, properties of objects, and even more complex locations specified by accessor functions. This generality makes setf an indispensable tool for manipulating data structures and objects in Common Lisp.

The power of setf lies in its ability to work with place forms. A place form is an expression that, when evaluated, returns a location that can be assigned to. For example, (car list) is a place form that refers to the first element of the list list. You can use setf to assign a new value to the first element of the list like this: (setf (car list) ’new-value). Similarly, you can use setf to assign values to fields of structures using accessor functions defined by defstruct, or to properties of objects using accessor functions defined by CLOS (Common Lisp Object System).

Here’s a practical example: You have a structure representing a person with fields like name and age. Using setf, you can easily update the age of a person: (setf (person-age my-person) 30). This demonstrates how setf provides a uniform way to assign values to different kinds of data locations, making your code more readable and maintainable. According to Peter Seibel in Practical Common Lisp, setf is “the workhorse of assignment in Common Lisp” [^2].

Infographic here
Choosing the Right Assignment Operator --------------------------------------

Selecting the appropriate assignment operator depends on the specific context and the type of assignment you need to perform. While setf can handle almost any assignment, it’s not always the most readable or efficient choice for simple variable assignments. Understanding the strengths and weaknesses of each operator allows you to write code that is both correct and idiomatic. Here’s a summary to guide your decision:

  • Use setq for simple variable assignments. It’s the most common and readable choice for this purpose.
  • Use set primarily for assigning values to global or dynamically bound variables, especially when you need to be explicit about the symbol being assigned to. However, consider if setq can be used instead for better readability.
  • Use setf for assigning values to complex locations, such as elements of arrays, fields of structures, or properties of objects. It’s the most versatile and powerful option for these scenarios.

Here are some general guidelines to follow:

  1. Identify the location you want to assign to (variable, array element, structure field, etc.).
  2. If it’s a simple variable, use setq.
  3. If it’s a complex location, use setf with the appropriate place form.
  4. If you are dealing with global variables and want to explicitly use a symbol, consider set, but usually setq is preferable.

By following these guidelines, you can ensure that you are using the most appropriate assignment operator for each situation, leading to cleaner, more efficient, and more maintainable Common Lisp code. Remember that consistent use of these operators contributes to the overall readability and understandability of your code, making it easier for others (and your future self) to work with. Consider exploring other advanced assignment macros like incf and decf for efficient numerical updates.

FAQ: Common Questions About Assignment in Lisp

What happens if I use set with an unquoted symbol?
If you use set with an unquoted symbol and that symbol is bound to a value, set will attempt to use that value as the name of the symbol to assign to. This will likely result in an error if there's no symbol with that name, or unexpected behavior if there is.
Can I use setq to assign values to array elements?
No, setq is designed for assigning values to variables. To assign values to array elements, you should use setf with the aref function (e.g., (setf (aref my-array 0) 10)).
Is setf slower than setq for simple variable assignments?
While setf has more overhead due to its generality, the performance difference is usually negligible for simple variable assignments. However, using setq for simple assignments is generally preferred for readability.
Best Practices and Conclusion -----------------------------

To further solidify your understanding, remember these key takeaways regarding the difference between set, setq, and setf in Common Lisp:

  • setq is your go-to for basic variable assignment due to its simplicity and readability.
  • set has niche uses involving global or dynamically scoped variables, but be cautious of its quoting behavior.
  • setf is the powerhouse for generalized assignments, enabling you to modify complex data structures elegantly.

By mastering these distinctions, you’ll write more robust and idiomatic Common Lisp code. Practice using each operator in different scenarios to truly internalize their behaviors. Explore the documentation for each function in your chosen Lisp implementation for deeper insights [^3]. As you continue your Lisp journey, remember that understanding these fundamentals is crucial for building complex and maintainable applications. Now, put your newfound knowledge to the test! Start experimenting with these assignment operators in your own projects, and watch your Lisp skills flourish. Consider exploring related topics such as lexical vs. dynamic scoping and the use of macros for further code optimization.

[^1]: Graham, Paul. ANSI Common Lisp. Prentice Hall, 1996. [^2]: Seibel, Peter. Practical Common Lisp. Apress, 2005. [^3]: HyperSpec: http://www.lispworks.com/documentation/common-lisp.html Question & Answer :
What is the difference between “set”, “setq”, and “setf” in Common Lisp?

Originally, in Lisp, there were no lexical variables – only dynamic ones. And there was no SETQ or SETF, just the SET function.

What is now written as:

(setf (symbol-value '*foo*) 42) 

was written as:

(set (quote *foo*) 42) 

which was eventually abbreviavated to SETQ (SET Quoted):

(setq *foo* 42) 

Then lexical variables happened, and SETQ came to be used for assignment to them too – so it was no longer a simple wrapper around SET.

Later, someone invented SETF (SET Field) as a generic way of assigning values to data structures, to mirror the l-values of other languages:

x.car := 42; 

would be written as

(setf (car x) 42) 

For symmetry and generality, SETF also provided the functionality of SETQ. At this point it would have been correct to say that SETQ was a Low-level primitive, and SETF a high-level operation.

Then symbol macros happened. So that symbol macros could work transparently, it was realized that SETQ would have to act like SETF if the “variable” being assigned to was really a symbol macro:

(defvar *hidden* (cons 42 42)) (define-symbol-macro foo (car *hidden*)) foo => 42 (setq foo 13) foo => 13 *hidden* => (13 . 42) 

So we arrive in the present day: SET and SETQ are atrophied remains of older dialects, and will probably be booted from eventual successors of Common Lisp.