I’ve written a few posts about features of the Lisp language that a newcomer arriving from C++ might not have encountered. I’m going through them alphabetically, so here is a summary page of the functions beginning with the letters N and P:
Tag Archives: programming
The less-familiar parts of Lisp for beginners — progv
Continuing our survey of obscure Lisp features, next is the progv special operator. This is a feature that allows the creation or local override of dynamic (special) variables at runtime. It binds the supplied dynamic variable names to supplied values for the duration of the progv block. There are some good examples in the CLHS, and I’ll review them briefly here.
The first example shows an existing special variable whose value is temporarily replaced within the progv, and in any functions called from it. When the progv form exits, the special variable reverts to its former value. If this is unfamiliar to you, review the side discussion on special variables in the earlier article about print.
Here’s the first example, adapted from the CLHS:
CL-USER> (defparameter *x* 1) *X* CL-USER> *x* 1 CL-USER> (progv '(*x*) '(2) *x*) 2 CL-USER> *x* 1
In the second example, a local variable is declared in a let, and the progv form lies underneath that. Despite the fact that the progv is nested within the let, it does not shadow the definition in the let, so a bare evaluation of the symbol returns the value assigned from the let. Note, though, that let does not intern a symbol, so symbol-value sees the value defined in the progv form. Also, the print-x function I define in the labels form sees the dynamic value of x, even though it is not passed as a parameter. The example, adapted from the CLHS, is here:
CL-USER> (labels ((print-x () (declare (special x)) (format t "~A~%" x))) (let ((x 3)) (progv '(x) '(4) (print-x) (list x (symbol-value 'x))))) 4 (3 4)
The less-familiar parts of Lisp for beginners — prog and prog*
Next in our survey of possibly unfamiliar Lisp features is a pair of somewhat unusual macros, prog and prog*. These macros fall squarely into the category of “syntactic sugar”. There’s nothing particularly special about these, they simplify the establishment of a particular sort of mini-environment.
Within prog, the programmer can declare, and optionally initialize, variables. Then, after an optional declaration (see declare), appears a sequence of go tags and statements. A go tag is any bare symbol or integer, not in parentheses, and is not evaluated. A statement is enclosed in parentheses, and is evaluated when flow encounters it. Within the statements, the programmer will typically use go to branch to a go tag in the prog body. Execution of the prog ends when flow passes to the end of the list of statements, or if a return statement is encountered (the entire body is enclosed in an unnamed block).
The typical use case for this is a state machine. Variables are assigned, flow enters the body, and operations are performed on data, with branches to different tags based on the values encountered.
The difference between prog and prog* is exactly like that between do and do*, or let and let*, in the variable declaration region. The * form of the macro allows variables declared in the list to depend on earlier variables in the same declaration.
The less-familiar parts of Lisp for beginners — proclaim
We talked about declare and declaim earlier, and now we come to proclaim. Generally, think of proclaim as being like declaim, but without any special relationship with the compiler. In a normal context, proclaim only has an effect once the form containing it is executed, and doesn’t do anything at compile time. The programmer might use this in a situation where declaration specifiers have to be handled at runtime, but the use cases are, in my experience, rare.
The less-familiar parts of Lisp for beginners — print-unreadable-object
Having discussed pretty-printing and print-object, now we come to a macro, print-unreadable-object, that is used to simplify the printing of objects that are deemed unreadable. You’ve probably seen such output in the past, when printing instances of CLOS classes. Where arrays and lists might print their contents, the Lisp printer just produces a brief output to indicate the class from which this instance was built, and an implentation-defined representation of the instance’s identity (often a memory address).
The programmer is likely to use this macro in a custom print-object method, to augment the normal printed representation of the class rather than printing the full contents. The HyperSpec contains a good example of the use in that case. Note that it can be used in other contexts, as follows:
CL-USER> (let ((mylist '(1 2 3))) (print-unreadable-object (mylist *standard-output* :type t :identity t) (format t "{{Uninteresting contents}}"))) #<CONS {{Uninteresting contents}} {1004DDE997}> NIL