Peter Siebel - Practical Common Lisp

Здесь есть возможность читать онлайн «Peter Siebel - Practical Common Lisp» весь текст электронной книги совершенно бесплатно (целиком полную версию без сокращений). В некоторых случаях можно слушать аудио, скачать через торрент в формате fb2 и присутствует краткое содержание. Год выпуска: 2005, ISBN: 2005, Издательство: Apress, Жанр: Программирование, на английском языке. Описание произведения, (предисловие) а так же отзывы посетителей доступны на портале библиотеки ЛибКат.

Practical Common Lisp: краткое содержание, описание и аннотация

Предлагаем к чтению аннотацию, описание, краткое содержание или предисловие (зависит от того, что написал сам автор книги «Practical Common Lisp»). Если вы не нашли необходимую информацию о книге — напишите в комментариях, мы постараемся отыскать её.

Practical Common Lisp — читать онлайн бесплатно полную книгу (весь текст) целиком

Ниже представлен текст книги, разбитый по страницам. Система сохранения места последней прочитанной страницы, позволяет с удобством читать онлайн бесплатно книгу «Practical Common Lisp», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.

Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

(do-primes var-and-range &rest body)

But with the new definition, it can tell you that a call should look like this:

(do-primes (var start end) &body body)

Destructuring parameter lists can contain &optional , &key , and &rest parameters and can contain nested destructuring lists. However, you don't need any of those options to write do-primes.

Generating the Expansion

Because do-primesis a fairly simple macro, after you've destructured the arguments, all that's left is to interpolate them into a template to get the expansion.

For simple macros like do-primes, the special backquote syntax is perfect. To review, a backquoted expression is similar to a quoted expression except you can "unquote" particular subexpressions by preceding them with a comma, possibly followed by an at (@) sign. Without an at sign, the comma causes the value of the subexpression to be included as is. With an at sign, the value—which must be a list—is "spliced" into the enclosing list.

Another useful way to think about the backquote syntax is as a particularly concise way of writing code that generates lists. This way of thinking about it has the benefit of being pretty much exactly what's happening under the covers—when the reader reads a backquoted expression, it translates it into code that generates the appropriate list structure. For instance, `(,a b)might be read as (list a 'b). The language standard doesn't specify exactly what code the reader must produce as long as it generates the right list structure.

Table 8-1 shows some examples of backquoted expressions along with equivalent list-building code and the result you'd get if you evaluated either the backquoted expression or the equivalent code. [94] APPEND , which I haven't discussed yet, is a function that takes any number of list arguments and returns the result of splicing them together into a single list.

Table 8-1. Backquote Examples

Backquote Syntax Equivalent List-Building Code Result
`(a (+ 1 2) c) (list 'a '(+ 1 2) 'c) (a (+ 1 2) c)
`(a ,(+ 1 2) c) (list 'a (+ 1 2) 'c) (a 3 c)
`(a (list 1 2) c) (list 'a '(list 1 2) 'c) (a (list 1 2) c)
`(a ,(list 1 2) c) (list 'a (list 1 2) 'c) (a (1 2) c)
`(a ,@(list 1 2) c) (append (list 'a) (list 1 2) (list 'c)) (a 1 2 c)

It's important to note that backquote is just a convenience. But it's a big convenience. To appreciate how big, compare the backquoted version of do-primesto the following version, which uses explicit list-building code:

(defmacro do-primes-a ((var start end) &body body)

(append '(do)

(list (list (list var

(list 'next-prime start)

(list 'next-prime (list '1+ var)))))

(list (list (list '> var end)))

body))

As you'll see in a moment, the current implementation of do-primesdoesn't handle certain edge cases correctly. But first you should verify that it at least works for the original example. You can test it in two ways. You can test it indirectly by simply using it—presumably, if the resulting behavior is correct, the expansion is correct. For instance, you can type the original example's use of do-primesto the REPL and see that it indeed prints the right series of prime numbers.

CL-USER> (do-primes (p 0 19) (format t "~d " p))

2 3 5 7 11 13 17 19

NIL

Or you can check the macro directly by looking at the expansion of a particular call. The function MACROEXPAND-1 takes any Lisp expression as an argument and returns the result of doing one level of macro expansion. [95] Another function, MACROEXPAND , keeps expanding the result as long as the first element of the resulting expansion is the name of the macro. However, this will often show you a much lower-level view of what the code is doing than you want, since basic control constructs such as DO are also implemented as macros. In other words, while it can be educational to see what your macro ultimately expands into, it isn't a very useful view into what your own macros are doing. Because MACROEXPAND-1 is a function, to pass it a literal macro form you must quote it. You can use it to see the expansion of the previous call. [96] If the macro expansion is shown all on one line, it's probably because the variable *PRINT-PRETTY* is NIL . If it is, evaluating (setf *print-pretty* t) should make the macro expansion easier to read.

CL-USER> (macroexpand-1 '(do-primes (p 0 19) (format t "~d " p)))

(DO ((P (NEXT-PRIME 0) (NEXT-PRIME (1+ P))))

((> P 19))

(FORMAT T "~d " P))

T

Or, more conveniently, in SLIME you can check a macro's expansion by placing the cursor on the opening parenthesis of a macro form in your source code and typing C-c RETto invoke the Emacs function slime-macroexpand-1, which will pass the macro form to MACROEXPAND-1 and "pretty print" the result in a temporary buffer.

However you get to it, you can see that the result of macro expansion is the same as the original handwritten expansion, so it seems that do-primesworks.

Plugging the Leaks

In his essay "The Law of Leaky Abstractions," Joel Spolsky coined the term leaky abstraction to describe an abstraction that "leaks" details it's supposed to be abstracting away. Since writing a macro is a way of creating an abstraction, you need to make sure your macros don't leak needlessly. [97] This is from Joel on Software by Joel Spolsky, also available at http://www.joelonsoftware.com/ articles/LeakyAbstractions.html . Spolsky's point in the essay is that all abstractions leak to some extent; that is, there are no perfect abstractions. But that doesn't mean you should tolerate leaks you can easily plug.

As it turns out, a macro can leak details of its inner workings in three ways. Luckily, it's pretty easy to tell whether a given macro suffers from any of those leaks and to fix them.

The current definition suffers from one of the three possible macro leaks: namely, it evaluates the endsubform too many times. Suppose you were to call do-primeswith, instead of a literal number such as 19, an expression such as (random 100)in the endposition.

(do-primes (p 0 (random 100))

(format t "~d " p))

Presumably the intent here is to loop over the primes from zero to whatever random number is returned by (random 100). However, this isn't what the current implementation does, as MACROEXPAND-1 shows.

CL-USER> (macroexpand-1 '(do-primes (p 0 (random 100)) (format t "~d " p)))

(DO ((P (NEXT-PRIME 0) (NEXT-PRIME (1+ P))))

((> P (RANDOM 100)))

(FORMAT T "~d " P))

T

When this expansion code is run, RANDOM will be called each time the end test for the loop is evaluated. Thus, instead of looping until pis greater than an initially chosen random number, this loop will iterate until it happens to draw a random number less than or equal to the current value of p. While the total number of iterations will still be random, it will be drawn from a much different distribution than the uniform distribution RANDOM returns.

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Похожие книги на «Practical Common Lisp»

Представляем Вашему вниманию похожие книги на «Practical Common Lisp» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.


Отзывы о книге «Practical Common Lisp»

Обсуждение, отзывы о книге «Practical Common Lisp» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.

x