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)