207

Well, technically those constructs could also expand into a LAMBDA expression since, as I mentioned in Chapter 6, LET could be defined—and was in some earlier Lisps—as a macro that expands into an invocation of an anonymous function.

208

Surprising as it may seem, it actually is possible to make anonymous functions recurse. However, you must use a rather esoteric mechanism known as the Y combinator. But the Y combinator is an interesting theoretical result, not a practical programming tool, so is well outside the scope of this book.

209

It's not required that WITH-SLOTS be implemented with SYMBOL-MACROLET—in some implementations, WITH- SLOTS may walk the code provided and generate an expansion with x, y, and z already replaced with the appropriate SLOT- VALUE forms. You can see how your implementation does it by evaluating this form:

(macroexpand-1 '(with-slots (x y z) obj (list x y z)))

However, walking the body is much easier for the Lisp implementation to do than for user code; to replace x, y, and z only when they appear in value positions requires a code walker that understands the syntax of all special operators and that recursively expands all macro forms in order to determine whether their expansions include the symbols in value positions. The Lisp implementation obviously has such a code walker at its disposal, but it's one of the few parts of Lisp that's not exposed to users of the language.

210

One version of f2cl is available as part of the Common Lisp Open Code Collection (CLOCC): http://clocc.sourceforge.net/. By contrast, consider the tricks the authors of f2j, a FORTRAN-to- Java translator, have to play. Although the Java Virtual Machine (JVM) has a goto instruction, it's not directly exposed in Java. So to compile FORTRAN gotos, they first compile the FORTRAN code into legal Java source with calls to a dummy class to represent the labels and gotos. Then they compile the source with a regular Java compiler and postprocess the byte codes to translate the dummy calls into JVM-level byte codes. Clever, but what a pain.

211

Since this algorithm depends on values returned by RANDOM, you may want to test it with a consistent random seed, which you can get by binding *RANDOM- STATE* to the value of (make-random-state nil) around each call to algorithm-s. For instance, you can do a basic sanity check of algorithm-s by evaluating this:

(let ((*random-state* (make-random-state nil))) (algorithm-s 10 200))

If your refactorings are all valid, this expression should evaluate to the same list each time.

212

This is a pretty reasonable restriction—it's not entirely clear what it'd mean to return from a form that has already returned—unless, of course, you're a Scheme programmer. Scheme supports continuations, a language construct that makes it possible to return from the same function call more than once. But for a variety of reasons, few, if any, languages other than Scheme support this kind of continuation.

213

If you're the kind of person who likes to know how things work all the way down to the bits, it may be instructive to think about how you might implement the condition system's macros using BLOCK, TAGBODY, closures, and dynamic variables.

214

UNWIND-PROTECT is essentially equivalent to try/finally constructs in Java and Python.

215

And indeed, CLSQL, the multi-Lisp, multidatabase SQL interface library, provides a similar macro called with-database. CLSQL's home page is at http://clsql.b9.com.

216

A small handful of macros don't pass through extra return values of the forms they evaluate. In particular, the PROG1 macro, which evaluates a number of forms like a PROGN before returning the value of the first form, returns that form's primary value only. Likewise, PROG2, which returns the value of the second of its subforms, returns only the primary value. The special operator MULTIPLE-VALUE- PROG1 is a variant of PROG1 that returns all the values returned by the first form. It's a minor wart that PROG1 doesn't already

Вы читаете Practical Common Lisp
Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату