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

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

Интервал:

Закладка:

Сделать

(format t "~:[FAIL~;pass~]" test-result)

Note that either clause can be empty, but the directive must contain a ~;.

Finally, with an at-sign modifier, the ~[directive can have only one clause. The directive consumes one argument and, if it's non- NIL , processes the clause after backing up to make the argument available to be consumed again.

(format nil "~@[x = ~a ~]~@[y = ~a~]" 10 20) ==> "x = 10 y = 20"

(format nil "~@[x = ~a ~]~@[y = ~a~]" 10 nil) ==> "x = 10 "

(format nil "~@[x = ~a ~]~@[y = ~a~]" nil 20) ==> "y = 20"

(format nil "~@[x = ~a ~]~@[y = ~a~]" nil nil) ==> ""

Iteration

Another FORMAT directive that you've seen already, in passing, is the iteration directive ~{. This directive tells FORMAT to iterate over the elements of a list or over the implicit list of the format arguments.

With no modifiers, ~{consumes one format argument, which must be a list. Like the ~[directive, which is always paired with a ~]directive, the ~{directive is always paired with a closing ~}. The text between the two markers is processed as a control string, which draws its arguments from the list consumed by the ~{directive. FORMAT will repeatedly process this control string for as long as the list being iterated over has elements left. In the following example, the ~{consumes the single format argument, the list (1 2 3), and then processes the control string "~a, ", repeating until all the elements of the list have been consumed.

(format nil "~{~a, ~}" (list 1 2 3)) ==> "1, 2, 3, "

However, it's annoying that in the output the last element of the list is followed by a comma and a space. You can fix that with the ~^directive; within the body of a ~{directive, the ~^causes the iteration to stop immediately, without processing the rest of the control string, when no elements remain in the list. Thus, to avoid printing the comma and space after the last element of a list, you can precede them with a ~^.

(format nil "~{~a~^, ~}" (list 1 2 3)) ==> "1, 2, 3"

The first two times through the iteration, there are still unprocessed elements in the list when the ~^is processed. The third time through, however, after the ~adirective consumes the 3, the ~^will cause FORMAT to break out of the iteration without printing the comma and space.

With an at-sign modifier, ~{processes the remaining format arguments as a list.

(format nil "~@{~a~^, ~}" 1 2 3) ==> "1, 2, 3"

Within the body of a ~{...~}, the special prefix parameter #refers to the number of items remaining to be processed in the list rather than the number of remaining format arguments. You can use that, along with the ~[directive, to print a comma-separated list with an "and" before the last item like this:

(format nil "~{~a~#[~;, and ~:;, ~]~}" (list 1 2 3)) ==> "1, 2, and 3"

However, that doesn't really work right if the list is two items long because it adds an extra comma.

(format nil "~{~a~#[~;, and ~:;, ~]~}" (list 1 2)) ==> "1, and 2"

You could fix that in a bunch of ways. The following takes advantage of the behavior of ~@{when nested inside another ~{or ~@{directive—it iterates over whatever items remain in the list being iterated over by the outer ~{. You can combine that with a ~#[directive to make the following control string for formatting lists according to English grammar:

(defparameter *english-list*

"~{~#[~;~a~;~a and ~a~:;~@{~a~#[~;, and ~:;, ~]~}~]~}")

(format nil *english-list* '()) ==> ""

(format nil *english-list* '(1)) ==> "1"

(format nil *english-list* '(1 2)) ==> "1 and 2"

(format nil *english-list* '(1 2 3)) ==> "1, 2, and 3"

(format nil *english-list* '(1 2 3 4)) ==> "1, 2, 3, and 4"

While that control string verges on being "write-only" code, it's not too hard to understand if you take it a bit at a time. The outer ~{...~} will consume and iterate over a list. The whole body of the iteration then consists of a ~#[...~]; the output generated each time through the iteration will thus depend on the number of items left to be processed from the list. Splitting apart the ~#[...~]directive on the ~;clause separators, you can see that it's made up of four clauses, the last of which is a default clause because it's preceded by a ~:;rather than a plain ~;. The first clause, for when there are zero elements to be processed, is empty, which makes sense—if there are no more elements to be processed, the iteration would've stopped already. The second clause handles the case of one element with a simple ~adirective. Two elements are handled with "~a and ~a". And the default clause, which handles three or more elements, consists of another iteration directive, this time using ~@{to iterate over the remaining elements of the list being processed by the outer ~{. And the body of that iteration is the control string that can handle a list of three or more elements correctly, which is fine in this context. Because the ~@{loop consumes all the remaining list items, the outer loop iterates only once.

If you wanted to print something special such as "" when the list was empty, you have a couple ways to do it. Perhaps the easiest is to put the text you want into the first (zeroth) clause of the outer ~#[and then add a colon modifier to the closing ~} of the outer iteration—the colon forces the iteration to be run at least once, even if the list is empty, at which point FORMAT processes the zeroth clause of the conditional directive.

(defparameter *english-list*

"~{~#[~;~a~;~a and ~a~:;~@{~a~#[~;, and ~:;, ~]~}~]~:}")

(format nil *english-list* '()) ==> ""

Amazingly, the ~{directive provides even more variations with different combinations of prefix parameters and modifiers. I won't discuss them other than to say you can use an integer prefix parameter to limit the maximum number of iterations and that, with a colon modifier, each element of the list (either an actual list or the list constructed by the ~@{directive) must itself be a list whose elements will then be used as arguments to the control string in the ~:{...~} directive.

Hop, Skip, Jump

A much simpler directive is the ~*directive, which allows you to jump around in the list of format arguments. In its basic form, without modifiers, it simply skips the next argument, consuming it without emitting anything. More often, however, it's used with a colon modifier, which causes it to move backward, allowing the same argument to be used a second time. For instance, you can use ~:*to print a numeric argument once as a word and once in numerals like this:

(format nil "~r ~:*(~d)" 1) ==> "one (1)"

Or you could implement a directive similar to ~:Pfor an irregular plural by combing ~:*with ~[.

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

Интервал:

Закладка:

Сделать

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

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


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

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

x