DOC PREVIEW
UMBC CMSC 331 - Read-Macros

This preview shows page 1-2 out of 6 pages.

Save
View full document
View full document
Premium Document
Do you want full access? Go Premium and unlock all 6 pages.
Access to all documents
Download any document
Ad free experience
View full document
Premium Document
Do you want full access? Go Premium and unlock all 6 pages.
Access to all documents
Download any document
Ad free experience
Premium Document
Do you want full access? Go Premium and unlock all 6 pages.
Access to all documents
Download any document
Ad free experience

Unformatted text preview:

17Read-MacrosThe three big moments in a Lisp expression’s life are read-time, compile-time,and runtime. Functions are in control at runtime. Macros give us a chance toperform transformations on programs at compile-time. This chapter discussesread-macros, which do their work at read-time.17.1 Macro CharactersIn keeping with the general philosophy of Lisp, you have a great deal of controlover the reader. Its behavior is controlled by properties and variables that canall be changed on the fly. The reader can be programmed at several levels. Theeasiest way to change its behavior is by defining new macro characters.A macro character is a character which exacts special treatment from the Lispreader. A lower-case a, for example, is ordinarily handled just like a lower-caseb, but a left parenthesis is something different: it tells Lisp to begin reading a list.Each such character has a function associated with it thattells the Lisp reader whatto do when the character is encountered. You can change the function associatedwith an existing macro character, or define new macro characters of your own.The built-in function set-macro-character provides one way to defineread-macros. It takes a character and a function, and thereafter when readencounters the character, it returns the result of calling the function.One of the oldest read-macros in Lisp is ’, the quote. You could do without’ by always writing (quote a) instead of ’a, but this would be tiresome andwould make your code harder to read. The quote read-macro makes it possible touse ’a as an abbreviation for (quote a). We could define it as in Figure 17.1.22417.1 MACRO CHARACTERS 225(set-macro-character #\’#’(lambda (stream char)(list ’quote (read stream t nil t))))Figure 17.1: Possible definition of ’.When read encounters an instance of ’ in a normal context (e.g. not in "a’b" or|a’b|), it will return the result of calling this function on the current stream andcharacter. (The function ignores this second parameter, which will always be thequote character.) So when read sees ’a, it will return (quote a).The last three arguments to read control respectively whether encounteringan end-of-file should cause an error, what value to return otherwise, and whetherthe call to read occurs within a call to read. In nearlyall read-macros,thesecondand fourth arguments should be t, and the third argument is therefore irrelevant.Read-macros and ordinary macros are both functions underneath. And likethe functions that generate macro expansions, the functions associated with macrocharacters shouldn’t have side-effects, except on the stream from which they read.Common Lisp explicitly makes no guarantees about when, or how often, thefunction associated with a read-macro will be called. (SeeCLTL2, p. 543.)Macros and read-macros see your program at different stages. Macros gethold of the program when it has already been parsed into Lisp objects by thereader, and read-macros operate on a program while it is still text. However, byinvokingread on this text, a read-macrocan, if it chooses, get parsed Lisp objectsas well. Thus read-macros are at least as powerful as ordinary macros.Indeed, read-macros are more powerful in at least two ways. A read-macroaffects everything read by Lisp, while a macro will only be expanded in code.And since read-macros generally call read recursively, an expression like’’abecomes(quote (quote a))whereas if we had tried to define an abbreviation for quote using a normal macro,(defmacro q (obj)‘(quote ,obj))226 READ-MACROS(set-dispatch-macro-character #\# #\?#’(lambda (stream char1 char2)‘#’(lambda (&rest ,(gensym)),(read stream t nil t))))Figure 17.2: A read-macro for constant functions.it would work in isolation,> (eq ’a (q a))Tbut not when nested. For example,(q (q a))would expand into(quote (q a))17.2 Dispatching Macro CharactersThe sharp-quote, like other read-macros beginning with #, is an example of asubspecies called dispatching read-macros. These appear as two characters, thefirst of which is called the dispatching character. The purpose of suchread-macrosis simply to make the most of theASCII character set; one can only have so manyone-character read-macros.You can (with make-dispatch-macro-character) define your own dis-patching macro characters, but since # is already defined as one, you may as welluse it. Some combinations beginning with # are explicitly reserved for your use;others are available in that they do not yet have a predefined meaning in CommonLisp. The complete list appears inCLTL2, p. 531.New dispatching macro character combinations can be defined by callingthe function set-dispatch-macro-character, like set-macro-characterexcept that it takes two character arguments. One of the combinations reservedto the programmer is #?. Figure 17.2 shows how to define this combination asa read-macro for constant functions. Now #?2 will be read as a function whichtakes any number of arguments and returns 2. For example:> (mapcar #?2 ’(a b c))(222)17.3 DELIMITERS 227(set-macro-character #\] (get-macro-character #\)))(set-dispatch-macro-character #\# #\[#’(lambda (stream char1 char2)(let ((accum nil)(pair (read-delimited-list #\] stream t)))(do ((i (ceiling (car pair)) (1+ i)))((> i (floor (cadr pair)))(list ’quote (nreverse accum)))(push i accum)))))Figure 17.3: A read-macro defining delimiters.This example makes the new operator look rather pointless, but in programs thatuse a lot of functional arguments, constant functions are often needed. In fact,some dialects provide a built-in function called always for defining them.Note that it is perfectly ok to use macro characters in the definition of thismacro character: as with any Lisp expression, they disappear when the definitionis read. It is also fine to use macro-characters after the #?. The definition of #?calls read, so macro-characters like ’ and #’ behave as usual:> (eq (funcall #?’a) ’a)T> (eq (funcall #?#’oddp) (symbol-function ’oddp))T17.3 DelimitersAfter simple macro characters, the most commonly defined macro charactersare list delimiters. Another character combination reserved for the user is #[.Figure 17.3 gives an example of how this character might be defined as a moreelaborate kind of left parenthesis. It defines an expression of the form #[x y] toread as a list of all the integers between x and y, inclusive:> #[2 7](234567)The only new thing about this read-macro is the call to


View Full Document

UMBC CMSC 331 - Read-Macros

Documents in this Course
Semantics

Semantics

14 pages

Java

Java

12 pages

Java

Java

31 pages

V

V

46 pages

Semantics

Semantics

11 pages

Load more
Download Read-Macros
Our administrator received your request to download this document. We will send you the file to your email shortly.
Loading Unlocking...
Login

Join to view Read-Macros and access 3M+ class-specific study document.

or
We will never post anything without your permission.
Don't have an account?
Sign Up

Join to view Read-Macros 2 2 and access 3M+ class-specific study document.

or

By creating an account you agree to our Privacy Policy and Terms Of Use

Already a member?