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», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.

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

Интервал:

Закладка:

Сделать

One last element of the public API, before I get to html, is another macro, in-html-style. This macro controls whether FOO generates XHTML or regular HTML by setting the *xhtml*variable. The reason this needs to be a macro is because you'll want to wrap the code that sets *xhtml*in an EVAL-WHEN so you can set it in a file and have it affect uses of the htmlmacro later in that same file.

(defmacro in-html-style (syntax)

(eval-when (:compile-toplevel :load-toplevel :execute)

(case syntax

(:html (setf *xhtml* nil))

(:xhtml (setf *xhtml* t)))))

Finally let's look at htmlitself. The only tricky bit about implementing htmlcomes from the need to generate code that can be used to generate both pretty and compact output, depending on the runtime value of the variable *pretty*. Thus, htmlneeds to generate an expansion that contains an IF expression and two versions of the code, one compiled with *pretty*bound to true and one compiled with it bound to NIL . To further complicate matters, it's common for one htmlcall to contain embedded calls to html, like this:

(html (:ul (dolist (item stuff)) (html (:li item))))

If the outer htmlexpands into an IF expression with two versions of the code, one for when *pretty*is true and one for when it's false, it's silly for nested htmlforms to expand into two versions too. In fact, it'll lead to an exponential explosion of code since the nested htmlis already going to be expanded twice—once in the *pretty*-is-true branch and once in the *pretty*-is-false branch. If each expansion generates two versions, then you'll have four total versions. And if the nested htmlform contained another nested htmlform, you'd end up with eight versions of that code. If the compiler is smart, it'll eventually realize that most of that generated code is dead and will eliminate it, but even figuring that out can take quite a bit of time, slowing down compilation of any function that uses nested calls to html.

Luckily, you can easily avoid this explosion of dead code by generating an expansion that locally redefines the htmlmacro, using MACROLET , to generate only the right kind of code. First you define a helper function that takes the vector of ops returned by sexp->opsand runs it through optimize-static-outputand generate-code—the two phases that are affected by the value of *pretty*—with *pretty*bound to a specified value and that interpolates the resulting code into a PROGN . (The PROGN returns NIL just to keep things tidy.).

(defun codegen-html (ops pretty)

(let ((*pretty* pretty))

`(progn ,@(generate-code (optimize-static-output ops)) nil)))

With that function, you can then define htmllike this:

(defmacro html (&whole whole &body body)

(declare (ignore body))

`(if *pretty*

(macrolet ((html (&body body) (codegen-html (sexp->ops body) t)))

(let ((*html-pretty-printer* (get-pretty-printer))) ,whole))

(macrolet ((html (&body body) (codegen-html (sexp->ops body) nil)))

,whole)))

The &whole parameter represents the original htmlform, and because it's interpolated into the expansion in the bodies of the two MACROLET s, it will be reprocessed with each of the new definitions of html, the one that generates pretty-printing code and the other that generates non-pretty-printing code. Note that the variable *pretty*is used both during macro expansion and when the resulting code is run. It's used at macro expansion time by codegen-htmlto cause generate-codeto generate one kind of code or the other. And it's used at runtime, in the IF generated by the top-level htmlmacro, to determine whether the pretty-printing or non-pretty-printing code should actually run.

The End of the Line

As usual, you could keep working with this code to enhance it in various ways. One interesting avenue to pursue is to use the underlying output generation framework to emit other kinds of output. In the version of FOO you can download from the book's Web site, you'll find some code that implements CSS output that can be integrated into HTML output in both the interpreter and compiler. That's an interesting case because CSS's syntax can't be mapped to s-expressions in such a trivial way as HTML's can. However, if you look at that code, you'll see it's still possible to define an s-expression syntax for representing the various constructs available in CSS.

A more ambitious undertaking would be to add support for generating embedded JavaScript. Done right, adding JavaScript support to FOO could yield two big wins. One is that after you define an s-expression syntax that you can map to JavaScript syntax, then you can start writing macros, in Common Lisp, to add new constructs to the language you use to write client-side code, which will then be compiled to JavaScript. The other is that, as part of the FOO s-expression JavaScript to regular JavaScript translation, you could deal with the subtle but annoying differences between JavaScript implementations in different browsers. That is, the JavaScript code that FOO generates could either contain the appropriate conditional code to do one thing in one browser and another in a different browser or could generate different code depending on which browser you wanted to support. Then if you use FOO in dynamically generated pages, it could use information about the User-Agent making the request to generate the right flavor of JavaScript for that browser.

But if that interests you, you'll have to implement it yourself since this is the end of the last practical chapter of this book. In the next chapter I'll wrap things up, discussing briefly some topics that I haven't touched on elsewhere in the book such as how to find libraries, how to optimize Common Lisp code, and how to deliver Lisp applications.

32. Conclusion: What's Next?

I hope by now you're convinced that the title of this book isn't an oxymoron. However, it's quite likely there's some area of programming that's of great practical importance to you that I haven't discussed at all. For instance, I haven't said anything about how to develop graphical user interfaces (GUIs), how to connect to relational databases, how to parse XML, or how to write programs that act as clients for various network protocols. Similarly, I haven't discussed two topics that will become important when you write real applications in Common Lisp: optimizing your Lisp code and packaging your application for delivery.

I'm obviously not going to cover all these topics in depth in this final chapter. Instead, I'll give you a few pointers you can use to pursue whichever aspect of Lisp programming interests you most.

Finding Lisp Libraries

While the standard library of functions, data types, and macros that comes with Common Lisp is quite large, it provides only general-purpose programming constructs. Specialized tasks such as writing GUIs, talking to databases, and parsing XML require libraries beyond what are provided by the ANSI standardized language.

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

Интервал:

Закладка:

Сделать

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

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


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

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

x