tags:

views:

1217

answers:

5

After making it through the major parts of an introductory Lisp book, I don't understand what the (quote) (or equivalent ') function does, yet it's been all over Lisp code that I've seen. What does it do?

+14  A: 

It says "don't evaluate me". For example, if you wanted to use a list as data, and not as code, you'd put a quote in front of it. For example,

(print '(+ 3 4)) prints "(+ 3 4)", whereas (print (+ 3 4)) prints "7"

Adam Rosenfield
+3  A: 

The quote prevents execution or evaluation of a form, turning it instead into data. In general you can execute the data by then eval'ing it.

quote creates list data structures, for example, the following are equivalent:

(quote a)
'a

It can also be used to create lists (or trees):

(quote (1 2 3))
'(1 2 3)

You're probably best off getting an introductary book on lisp, such as Practical Common Lisp (which is available to read on-line).

Kyle Burton
+2  A: 

One answer to this question says that QUOTE “creates list data structures”. This isn't quite right. QUOTE is more fundamental than this. In fact, QUOTE is a trivial operator: Its purpose is to prevent anything from happening at all. In particular, it doesn't create anything.

What (QUOTE X) says is basically “don't do anything, just give me X.” X needn't be a list as in (QUOTE (A B C)) or a symbol as in (QUOTE FOO). It can be any object whatever. Indeed, the result of evaluating the list that is produced by (LIST 'QUOTE SOME-OBJECT) will always just return SOME-OBJECT, whatever it is.

Now, the reason that (QUOTE (A B C)) seems as if it created a list whose elements are A, B, and C is that such a list really is what it returns; but at the time the QUOTE form is evaluated, the list has generally already been in existence for a while (as a component of the QUOTE form!), created either by the loader or the reader prior to execution of the code.

One implication of this that tends to trip up newbies fairly often is that it's very unwise to modify a list returned by a QUOTE form. Data returned by QUOTE is, for all intents and purposes, to be considered as part of the code being executed and should therefore be treated as read-only!

Matthias Benkard
+17  A: 

Short answer Bypass the default evaluation rules and do not evaluate the expression (symbol or s-exp), passing it along to the function exactly as typed.

Long Answer: The Default Evaluation Rule

When a regular (I'll come to that later) function is invoked, all arguments passed to it are evaluated. This means you can write this:

(* (+ a 2)
   3)

Which in turn evaluates (+ a 2), by evaluating a and 2. The value of the symbol a is looked up in the current variable binding set, and then replaced. Say a is currently bound to the value 3:

(let ((a 3))
  (* (+ a 2)
     3))

We'd get (+ 3 2), + is then invoked on 3 and 2 yielding 5. Our original form is now (* 5 3) yielding 15.

Explain quote Already!

Alright. As seen above, all arguments to a function are evaluated, so if you would like to pass the symbol a and not its value, you don't want to evaluate it. Lisp symbols can double both as their values, and markers where you in other languages would have used strings, such as keys to hash tables.

This is where quote comes in. Say you want to plot resource allocations from a Python application, but rather do the plotting in Lisp. Have your Python app do something like this:

print "'("
while allocating:
    if random.random() > 0.5:
        print "(allocate %d)" random.randint(0, 20)
    else:
        print "(free %d)" % random.randint(0, 20)
    ...
print ")"

Giving you output looking like this (slightly prettyfied):

'((allocate 3)
  (allocate 7)
  (free 14)
  (allocate 19)
  ...)

Remember what I said about quote ("tick") causing the default rule not to apply? Good. What would otherwise happen is that the values of allocate and free are looked up, and we don't want that. In our Lisp, we wish to do:

(dolist (entry allocation-log)
  (case (first entry)
    (allocate (plot-allocation (second entry)))
    (free (plot-free (second entry)))))

For the data given above, the following sequence of function calls would have been made:

(plot-allocation 3)
(plot-allocation 7)
(plot-free 14)
(plot-allocation 19)

But What About list?

Well, sometimes you do want to evaluate the arguments. Say you have a nifty function manipulating a number and a string and returning a list of the resulting ... things. Let's make a false start:

(defun mess-with (number string)
  '(value-of-number (1+ number) something-with-string (length string)))

Lisp> (mess-with 20 "foo")
(VALUE-OF-NUMBER (1+ NUMBER) SOMETHING-WITH-STRING (LENGTH STRING))

Hey! That's not what we wanted. We want to selectively evaluate some arguments, and leave the others as symbols. Try #2!

(defun mess-with (number string)
  (list 'value-of-number (1+ number) 'something-with-string (length string)))

Lisp> (mess-with 20 "foo")
(VALUE-OF-NUMBER 21 SOMETHING-WITH-STRING 3)

Not Just quote, But backquote

Much better! Incidently, this pattern is so common in (mostly) macros, that there is special syntax for doing just that. The backquote:

(defun mess-with (number string)
  `(value-of-number ,(1+ number) something-with-string ,(length string)))

It's like using quote, but with the option to explicitly evaluate some arguments by prefixing them with comma. The result is equivalent to using list, but if you're generating code from a macro you often only want to evaluate small parts of the code returned, so the backquote is more suited. For shorter lists, list can be more readable.

Hey, You Forgot About quote!

So, where does this leave us? Oh right, what does quote actually do? It simply returns its argument(s) unevaluated! Remember what I said in the beginning about regular functions? Turns out that some operators/functions need to not evaluate their arguments. Such as IF -- you wouldn't want the else branch to be evaluated if it wasn't taken, right? So-called special operators, together with macros, work like that. Special operators are also the "axiom" of the language -- minimal set of rules -- upon which you can implement the rest of Lisp by combining them together in different ways.

Back to quote, though:

Lisp> (quote spiffy-symbol)
SPIFFY-SYMBOL

Lisp> 'spiffy-symbol ; ' is just a shorthand ("reader macro"), as shown above
SPIFFY-SYMBOL

Compare to (on Steel-Bank Common Lisp):

Lisp> spiffy-symbol
debugger invoked on a UNBOUND-VARIABLE in thread #<THREAD "initial thread" RUNNING   {A69F6A9}>:
  The variable SPIFFY-SYMBOL is unbound.

Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
  0: [ABORT] Exit debugger, returning to top level.

(SB-INT:SIMPLE-EVAL-IN-LEXENV SPIFFY-SYMBOL #<NULL-LEXENV>)
0]

Because there is no spiffy-symbol in the current scope!

Summing Up

quote, backquote (with comma), and list are some of the tools you use to create lists, that are not only lists of values, but as you seen can be used as lightweight (no need to define a struct) data structures!

If you wish to learn more, I recommend Peter Seibel's book Practical Common Lisp for a practical approach to learning Lisp, if you're already into programming at large. Eventually on your Lisp journey, you'll start using packages too. Ron Garret's The Idiot's Guide to Common Lisp Packages will give you good explanation of those.

Happy hacking!

Mikael Jansson
+1  A: 

Other people have answered this question admirably, and Matthias Benkard brings up an excellent warning.

DO NOT USE QUOTE TO CREATE LISTS THAT YOU WILL LATER MODIFY. The spec allows the compiler to treat quoted lists as constants. Often, a compiler will optimize constants by creating a single value for them in memory and then referencing that single value from all locations where the constant appears. In other words, it may treat the constant like an anonymous global variable.

This can cause obvious problems. If you modify a constant, it may very well modify other uses of the same constant in completely unrelated code. For example, you may compare some variable to '(1 1) in some function, and in a completely different function, start a list with '(1 1) and then add more stuff to it. Upon running these functions, you may find that the first function doesn't match things properly anymore, because it's now trying to compare the variable to '(1 1 2 3 5 8 13), which is what the second function returned. These two functions are completely unrelated, but they have an effect on each other because of the use of constants. Even crazier bad effects can happen, like a perfectly normal list iteration suddenly infinite looping.

Use quote when you need a constant list, such as for comparison. Use list when you will be modifying the result.

Xanthir