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

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

Интервал:

Закладка:

Сделать

(defmacro define-html-special-operator (name (processor &rest other-parameters) &body body)

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

(setf (get ',name 'html-special-operator)

(lambda (,processor ,@other-parameters) ,@body))))

This is a fairly advanced type of macro, but if you take it one line at a time, there's nothing all that tricky about it. To see how it works, take a simple use of the macro, the definition of the special operator :noescape, and look at the macro expansion. If you write this:

(define-html-special-operator :noescape (processor &rest body)

(let ((*escapes* nil))

(loop for exp in body do (process processor exp))))

it's as if you had written this:

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

(setf (get ':noescape 'html-special-operator)

(lambda (processor &rest body)

(let ((*escapes* nil))

(loop for exp in body do (process processor exp))))))

The EVAL-WHEN special operator, as I discussed in Chapter 20, ensures that the effects of code in its body will be made visible during compilation when you compile with COMPILE-FILE . This matters if you want to use define-html-special-operatorin a file and then use the just-defined special operator in that same file.

Then the SETF expression sets the property html-special-operatoron the symbol :noescapeto an anonymous function with the same parameter list as was specified in define-html-special-operator. By defining define-html-special-operatorto split the parameter list in two parts, processorand everything else, you ensure that all special operators accept at least one argument.

The body of the anonymous function is then the body provided to define-html-special-operator. The job of the anonymous function is to implement the special operator by making the appropriate calls on the backend interface to generate the correct HTML or the code that will generate it. It can also use processto evaluate an expression as a FOO form.

The :noescapespecial operator is particularly simple—all it does is pass the forms in its body to processwith *escapes*bound to NIL . In other words, this special operator disables the normal character escaping preformed by process-sexp-html.

With special operators defined this way, all process-special-formhas to do is look up the anonymous function in the property list of the special operator's name and APPLY it to the processor and rest of the form.

(defun process-special-form (processor form)

(apply (get (car form) 'html-special-operator) processor (rest form)))

Now you're ready to define the five remaining FOO special operators. Similar to :noescapeis :attribute, which evaluates the forms in its body with *escapes*bound to *attribute-escapes*. This special operator is useful if you want to write helper functions that output attribute values. If you write a function like this:

(defun foo-value (something)

(html (:print (frob something))))

the htmlmacro is going to generate code that escapes the characters in *element-escapes*. But if you're planning to use foo-valuelike this:

(html (:p :style (foo-value 42) "Foo"))

then you want it to generate code that uses *attribute-escapes*. So, instead, you can write it like this: [319] The :noescape and :attribute special operators must be defined as special operators because FOO determines what escapes to use at compile time, not at runtime. This allows FOO to escape literal values at compile time, which is much more efficient than having to scan all output at runtime.

(defun foo-value (something)

(html (:attribute (:print (frob something)))))

The definition of :attributelooks like this:

(define-html-special-operator :attribute (processor &rest body)

(let ((*escapes* *attribute-escapes*))

(loop for exp in body do (process processor exp))))

The next two special operators, :printand :format, are used to output values. The :printspecial operator, as I discussed earlier, is used in compiled FOO programs to embed the value of an arbitrary Lisp expression. The :formatspecial operator is more or less equivalent to generating a string with (format nil ...)and then embedding it. The primary reason to define :formatas a special operator is for convenience. This:

(:format "Foo: ~d" x)

is nicer than this:

(:print (format nil "Foo: ~d" x))

It also has the slight advantage that if you use :formatwith arguments that are all self-evaluating, FOO can evaluate the :formatat compile time rather than waiting until runtime. The definitions of :printand :formatare as follows:

(define-html-special-operator :print (processor form)

(cond

((self-evaluating-p form)

(warn "Redundant :print of self-evaluating form ~s" form)

(process-sexp-html processor form))

(t

(embed-value processor form))))

(define-html-special-operator :format (processor &rest args)

(if (every #'self-evaluating-p args)

(process-sexp-html processor (apply #'format nil args))

(embed-value processor `(format nil ,@args))))

The :newlinespecial operator forces an output of a literal newline, which is occasionally handy.

(define-html-special-operator :newline (processor)

(newline processor))

Finally, the :prognspecial operator is analogous to the PROGN special operator in Common Lisp. It simply processes the forms in its body in sequence.

(define-html-special-operator :progn (processor &rest body)

(loop for exp in body do (process processor exp)))

In other words, the following:

(html (:p (:progn "Foo " (:i "bar") " baz")))

will generate the same code as this:

(html (:p "Foo " (:i "bar") " baz"))

This might seem like a strange thing to need since normal FOO expressions can have any number of forms in their body. However, this special operator will come in quite handy in one situation—when writing FOO macros, which brings you to the last language feature you need to implement.

FOO Macros

FOO macros are similar in spirit to Common Lisp's macros. A FOO macro is a bit of code that accepts a FOO expression as an argument and returns a new FOO expression as the result, which is then evaluated according to the normal FOO evaluation rules. The actual implementation is quite similar to the implementation of special operators.

As with special operators, you can define a predicate function to test whether a given form is a macro form.

(defun macro-form-p (form)

(cons-form-p form #'(lambda (x) (and (symbolp x) (get x 'html-macro)))))

You use the previously defined function cons-form-pbecause you want to allow macros to be used in either of the syntaxes of nonmacro FOO cons forms. However, you need to pass a different predicate function, one that tests whether the form name is a symbol with a non- NILhtml-macroproperty. Also, as in the implementation of special operators, you'll define a macro for defining FOO macros, which is responsible for storing a function in the property list of the macro's name, under the key html-macro. However, defining a macro is a bit more complicated because FOO supports two flavors of macro. Some macros you'll define will behave much like normal HTML elements and may want to have easy access to a list of attributes. Other macros will simply want raw access to the elements of their body.

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

Интервал:

Закладка:

Сделать

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

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


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

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

x