Skip to main content

Chapter 8: The Lisp Reader

  • Chapter
  • 2045 Accesses

Abstract

Whatever you enter into your computer (whether interactively or via a file containing source code) has to be parsed first. The part of your Lisp system that consumes characters one by one and tries to make sense of them is called the Lisp reader. Its behavior is clearly specified (as is pretty much everything in Common Lisp), but it also is configurable (as is pretty much everything in Common Lisp) so that you can bend it to your will.

This is a preview of subscription content, log in via an institution.

Buying options

Chapter
USD   29.95
Price excludes VAT (USA)
  • Available as PDF
  • Read on any device
  • Instant download
  • Own it forever
eBook
USD   79.99
Price excludes VAT (USA)
  • Available as EPUB and PDF
  • Read on any device
  • Instant download
  • Own it forever
Softcover Book
USD   99.99
Price excludes VAT (USA)
  • Compact, lightweight edition
  • Dispatched in 3 to 5 business days
  • Free shipping worldwide - see info

Tax calculation will be finalised at checkout

Purchases are for personal use only

Learn about institutional subscriptions

Notes

  1. 1.

    For a very elaborate example, see XMLisp at http://agentsheets.com/lisp/XMLisp/ .

    You might also want to check out the #I infix reader macro by Mark Kantrowitz, the #U reader macro in the PURI libary, or CL-INTERPOL.

  2. 2.

    In case you’re wondering why we had to write T NIL before :START, this is explained later in this recipe.

  3. 3.

    Note how the fraction was automatically canceled and the complex number converted into an integer. See Chapter 4 for more about this.

  4. 4.

    See Chapter 1

  5. 5.

    For READ-FROM-STRING it is even worse because it mixes optional with keyword arguments which is something you should never ever do. This is certainly one of those things that would be different if Common Lisp were a greenfield project.

  6. 6.

    This is, of course, not an issue with immediate objects like numbers and characters because they aren’t comprised of constituents that can be changed. (While technically a rational number—see Recipe 4-5—has a numerator and a denominator, there’s no portable way to, say, modify the denominator of 2/3 so that it suddenly is 2/7 instead.)

  7. 7.

    Well, unless you have a sufficiently clever compiler that recognizes that this is a constant value. But bear with me for the sake of this example.

  8. 8.

    Really any form, no matter how complicated. You could even, say, read and process a whole file of data and use this syntax to insert the results into your source code before it is compiled.

  9. 9.

    This, by the way, can also have an effect on how objects are printed. See page 225 and the HyperSpec dictionary entry for *PRINT-READABLY*.

  10. 10.

    But that is rarely, if ever, a good idea anyway! See also Recipe 8-1.

  11. 11.

    See Recipe 22-9 for GET-UNIVERSAL-TIME.

  12. 12.

    It’ll also accept lambda expressions, but you’ll probably never need that.

  13. 13.

    With the caveat that MACROLET is also relevant here. If you were to nest a MACROLET inside the body of a LABELS or FLET, and if you’d use the same name for a local macro as for a local function defined in an enclosing form, you wouldn’t be able to access the function anymore.

  14. 14.

    With LOOP, you’d just write (LOOP FOR X = (PREPARE-AND-COMPUTE-THE-NEXT-VALUE)...).

  15. 15.

    See also Recipe 7-6.

  16. 16.

    Although the compiler is allowed to coalesce them (see Chapter 3 of the HyperSpec) which would mean that the first form could return (T T).

  17. 17.

    The only way to perform tests this way would be with calls to functions like READ or READ-FROM-STRING in the LET body (see Recipe 8-1).

  18. 18.

    Unless, that is, you’ve done something very devious like changing the syntax of *.

  19. 19.

    Technically, the argument is a readtable designator—similar to the function designators mentioned in Recipe 8-5. But that’s a bit of a mouthful for such a simple concept.

  20. 20.

    So, if you’re just trying out things, you won’t even need the first call to COPY-READTABLE.

  21. 21.

    See Recipe 4-4 for more about *READ-BASE*.

  22. 22.

    We list six here. The standard, in section 2.1.4, also lists a syntax type invalid, but it mentions no character that actually has this syntax type, and from the wording in other sections, one can infer that invalid is merely a constituent trait. (Constituent traits are explained at the end of this recipe.)

  23. 23.

    But see Recipe 8-11.

  24. 24.

    You might have noticed a small detail in this example: when the symbol is printed after it has been read, the backslash is used as the escape character; although you might think the dollar sign could have been used as well.

    And even if you change the syntax of the backslash character so that it isn’t an escape character anymore, it will still be used as an escape character in output. This is because the Lisp printer will—if it tries to make its output readable (see Recipe 14-13)—assume the standard readtable (see Recipe 8-7) to be present.

  25. 25.

    At this point, you might be wondering if I really wanted to say: “up to the next multiple escape character” and you’re kind of right. However, even between multiple escape characters, single escape characters are still special. That’s so you can type strange stuff like ’a|()/|()|b—in case you ever need it…

  26. 26.

    Except, in a way, for macro characters. See the following recipes.

  27. 27.

    So, if you have figure 2-7 of the HyperSpec handy, you’ll always find a character to copy from if you need a specific syntax type.

  28. 28.

    See Recipe 16-11 for the meaning of *.

  29. 29.

    Unfortunately, we’ll have to cope with this three-word construct throughout because technically a reader macro is something different.

  30. 30.

    The standard itself mentions that this won’t work as expected if you wanted to replace parentheses with, say, brackets. You might think it would suffice to copy the reader macro function from the open parenthesis, but it’ll look for a closing parenthesis and not for a closing bracket. So you’ll have to roll your own reader macro function instead of copying one—which is what this recipe is mainly about.

  31. 31.

    This character can often be ignored, as in our example, but it might make sense to actually use it in the case of several macro characters sharing the same code. That’s the reason our double quote example worked.

  32. 32.

    The third argument to READ-DELIMITED-LIST is T, meaning that the function is not called as a stand-alone function but rather as part of a process involving the Lisp reader. In short, you should always call it like this from reader macro functions. The subtle details are explained in section 23.1.3.2 of the standard.

  33. 33.

    Well, the error message might talk about a “parenthesis,” while we’d rather see the word “brace” there, but let’s leave it at that.

  34. 34.

    And its second argument is again a readtable designator; see Recipe 8-7.

  35. 35.

    This sign is called sharpsign in the Common Lisp standard, but today we distinguish between the musical symbol and the one used in technical disciplines, which is usually called number sign or hash sign. I’m nevertheless using sharpsign throughout in order to be in accordance with the HyperSpec.

  36. 36.

    Of course, with Unicode there are lots of different characters. But there probably aren’t many that are convenient to type and at the same time not something you’d rather have as a constituent character.

  37. 37.

    That’s why decimal digits obviously don’t make sense as sub-characters.

  38. 38.

    You could also do this with SET-SYNTAX-FROM-CHAR (see Recipe 8-8), but that’s rarely a good idea, because that would copy the entire dispatch table of the character you copied the syntax from.

  39. 39.

    There are two spaces between the numbers 42 and 23.

  40. 40.

    The dictionary entry for READ-PRESERVING-WHITESPACE has a good example for such a modification.

Author information

Authors and Affiliations

Authors

Electronic Supplementary Material

Below is the link to the electronic supplementary material.

chapter-08 (zip 2 kb)

Rights and permissions

Reprints and permissions

Copyright information

© 2016 Edmund Weitz

About this chapter

Cite this chapter

Weitz, E. (2016). Chapter 8: The Lisp Reader. In: Common Lisp Recipes. Apress, Berkeley, CA. https://doi.org/10.1007/978-1-4842-1176-2_8

Download citation

Publish with us

Policies and ethics