Peter Siebel - Practical Common Lisp
Здесь есть возможность читать онлайн «Peter Siebel - Practical Common Lisp» весь текст электронной книги совершенно бесплатно (целиком полную версию без сокращений). В некоторых случаях можно слушать аудио, скачать через торрент в формате fb2 и присутствует краткое содержание. Год выпуска: 2005, ISBN: 2005, Издательство: Apress, Жанр: Программирование, на английском языке. Описание произведения, (предисловие) а так же отзывы посетителей доступны на портале библиотеки ЛибКат.
- Название:Practical Common Lisp
- Автор:
- Издательство:Apress
- Жанр:
- Год:2005
- ISBN:1-59059-239-5
- Рейтинг книги:4 / 5. Голосов: 1
-
Избранное:Добавить в избранное
- Отзывы:
-
Ваша оценка:
- 80
- 1
- 2
- 3
- 4
- 5
Practical Common Lisp: краткое содержание, описание и аннотация
Предлагаем к чтению аннотацию, описание, краткое содержание или предисловие (зависит от того, что написал сам автор книги «Practical Common Lisp»). Если вы не нашли необходимую информацию о книге — напишите в комментариях, мы постараемся отыскать её.
Practical Common Lisp — читать онлайн бесплатно полную книгу (весь текст) целиком
Ниже представлен текст книги, разбитый по страницам. Система сохранения места последней прочитанной страницы, позволяет с удобством читать онлайн бесплатно книгу «Practical Common Lisp», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.
Интервал:
Закладка:
(defparameter *r* 25)
(defun standard-header ()
(html
((:p :class "toolbar")
"[" (:a :href (link "/browse" :what "genre") "All genres") "] "
"[" (:a :href (link "/browse" :what "genre" :random *r*) "Random genres") "] "
"[" (:a :href (link "/browse" :what "artist") "All artists") "] "
"[" (:a :href (link "/browse" :what "artist" :random *r*) "Random artists") "] "
"[" (:a :href (link "/browse" :what "album") "All albums") "] "
"[" (:a :href (link "/browse" :what "album" :random *r*) "Random albums") "] "
"[" (:a :href (link "/browse" :what "song" :random *r*) "Random songs") "] "
"[" (:a :href (link "/playlist") "Playlist") "] "
"[" (:a :href (link "/all-playlists") "All playlists") "]")))
(defun standard-footer ()
(html (:hr) ((:p :class "footer") "MP3 Browser v" *major-version* "." *minor-version*)))
A couple of smaller HTML macros and helper functions automate other common patterns. The :table-row
HTML macro makes it easier to generate the HTML for a single row of a table. It uses a feature of FOO that I'll discuss in Chapter 31, an &attributes
parameter, which causes uses of the macro to be parsed just like normal s-expression HTML forms, with any attributes gathered into a list that will be bound to the &attributes
parameter. It looks like this:
(define-html-macro :table-row (&attributes attrs &rest values)
`(:tr ,@attrs ,@(loop for v in values collect `(:td ,v))))
And the link
function generates a URL back into the application to be used as the HREF
attribute with an A
element, building a query string out of a set of keyword/value pairs and making sure all special characters are properly escaped. For instance, instead of writing this:
(:a :href "browse?what=artist&genre=Rhythm+%26+Blues" "Artists")
you can write the following:
(:a :href (link "browse" :what "artist" :genre "Rhythm & Blues") "Artists")
It looks like this:
(defun link (target &rest attributes)
(html
(:attribute
(:format "~a~@[?~{~(~a~)=~a~^&~}~]" target (mapcar #'urlencode attributes)))))
To URL encode the keys and values, you use the helper function urlencode
, which is a wrapper around the function encode-form-urlencoded
, which is a nonpublic function from AllegroServe. This is—on one hand—bad form; since the name encode-form-urlencoded
isn't exported from NET.ASERVE
, it's possible that encode-form-urlencoded
may go away or get renamed out from under you. On the other hand, using this unexported symbol for the time being lets you get work done for the moment; by wrapping encode-form-urlencoded
in your own function, you isolate the crufty code to one function, which you could rewrite if you had to.
(defun urlencode (string)
(net.aserve::encode-form-urlencoded string))
Finally, you need the CSS style sheet mp3-browser.css
used by :mp3-browser-page
. Since there's nothing dynamic about it, it's probably easiest to just publish a static file with publish-file
.
(publish-file :path "/mp3-browser.css" :file filename :content-type "text/css")
A sample style sheet is included with the source code for this chapter on the book's Web site. You'll define a function, at the end of this chapter, that starts the MP3 browser application. It'll take care of, among other things, publishing this file.
The Browse Page
The first URL function will generate a page for browsing the MP3 database. Its query parameters will tell it what kind of thing the user is browsing and provide the criteria of what elements of the database they're interested in. It'll give them a way to select database entries that match a specific genre, artist, or album. In the interest of serendipity, you can also provide a way to select a random subset of matching items. When the user is browsing at the level of individual songs, the title of the song will be a link that causes that song to be added to the playlist. Otherwise, each item will be presented with links that let the user browse the listed item by some other category. For example, if the user is browsing genres, the entry "Blues" will contain links to browse all albums, artists, and songs in the genre Blues. Additionally, the browse page will feature an "Add all" button that adds every song matching the page's criteria to the user's playlist. The function looks like this:
(define-url-function browse
(request (what keyword :genre) genre artist album (random integer))
(let* ((values (values-for-page what genre artist album random))
(title (browse-page-title what random genre artist album))
(single-column (if (eql what :song) :file what))
(values-string (values->base-64 single-column values)))
(html
(:mp3-browser-page
(:title title)
((:form :method "POST" :action "playlist")
(:input :name "values" :type "hidden" :value values-string)
(:input :name "what" :type "hidden" :value single-column)
(:input :name "action" :type "hidden" :value :add-songs)
(:input :name "submit" :type "submit" :value "Add all"))
(:ul (do-rows (row values) (list-item-for-page what row)))))))
This function starts by using the function values-for-page
to get a table containing the values it needs to present. When the user is browsing by song—when the what
parameter is :song
—you want to select complete rows from the database. But when they're browsing by genre, artist, or album, you want to select only the distinct values for the given category. The database function select
does most of the heavy lifting, with values-for-page
mostly responsible for passing the right arguments depending on the value of what
. This is also where you select a random subset of the matching rows if necessary.
(defun values-for-page (what genre artist album random)
(let ((values
(select
:from *mp3s*
:columns (if (eql what :song) t what)
:where (matching *mp3s* :genre genre :artist artist :album album)
:distinct (not (eql what :song))
:order-by (if (eql what :song) '(:album :track) what))))
(if random (random-selection values random) values)))
To generate the title for the browse page, you pass the browsing criteria to the following function, browse-page-title
:
(defun browse-page-title (what random genre artist album)
(with-output-to-string (s)
(when random (format s "~:(~r~) Random " random))
(format s "~:(~a~p~)" what random)
(when (or genre artist album)
(when (not (eql what :song)) (princ " with songs" s))
(when genre (format s " in genre ~a" genre))
(when artist (format s " by artist ~a " artist))
(when album (format s " on album ~a" album)))))
Once you have the values you want to present, you need to do two things with them. The main task, of course, is to present them, which happens in the do-rows
loop, leaving the rendering of each row to the function list-item-for-page
. That function renders :song
rows one way and all other kinds another way.
Интервал:
Закладка:
Похожие книги на «Practical Common Lisp»
Представляем Вашему вниманию похожие книги на «Practical Common Lisp» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.
Обсуждение, отзывы о книге «Practical Common Lisp» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.