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», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.
Интервал:
Закладка:
(defun list-item-for-page (what row)
(if (eql what :song)
(with-column-values (song file album artist genre) row
(html
(:li
(:a :href (link "playlist" :file file :action "add-songs") (:b song)) " from "
(:a :href (link "browse" :what :song :album album) album) " by "
(:a :href (link "browse" :what :song :artist artist) artist) " in genre "
(:a :href (link "browse" :what :song :genre genre) genre))))
(let ((value (column-value row what)))
(html
(:li value " - "
(browse-link :genre what value)
(browse-link :artist what value)
(browse-link :album what value)
(browse-link :song what value))))))
(defun browse-link (new-what what value)
(unless (eql new-what what)
(html
"["
(:a :href (link "browse" :what new-what what value) (:format "~(~as~)" new-what))
"] ")))
The other thing on the browse
page is a form with several hidden INPUT
fields and an "Add all" submit button. You need to use an HTML form instead of a regular link to keep the application stateless—to make sure all the information needed to respond to a request comes in the request itself. Because the browse page results can be partially random, you need to submit a fair bit of data for the server to be able to reconstitute the list of songs to add to the playlist. If you didn't allow the browse page to return randomly generated results, you wouldn't need much data—you could just submit a request to add songs with whatever search criteria the browse page used. But if you added songs that way, with criteria that included a random
argument, then you'd end up adding a different set of random songs than the user was looking at on the page when they hit the "Add all" button.
The solution you'll use is to send back a form that has enough information stashed away in a hidden INPUT
element to allow the server to reconstitute the list of songs matching the browse page criteria. That information is the list of values returned by values-for-page
and the value of the what
parameter. This is where you use the base64-list
parameter type; the function values->base64
extracts the values of a specified column from the table returned by values-for-page
into a list and then makes a base 64-encoded string out of that list to embed in the form.
(defun values->base-64 (column values-table)
(flet ((value (r) (column-value r column)))
(obj->base64 (map-rows #'value values-table))))
When that parameter comes back as the value of the values
query parameter to a URL function that declares values
to be of type base-64-list
, it'll be automatically converted back to a list. As you'll see in a moment, that list can then be used to construct a query that'll return the correct list of songs. [310] This solution has its drawbacks—if a browse page returns a lot of results, a fair bit of data is going back and forth under the covers. Also, the database queries aren't necessarily the most efficient. But it does keep the application stateless. An alternative approach is to squirrel away, on the server side, information about the results returned by browse and then, when a request to add songs come in, find the appropriate bit of information in order to re-create the correct set of songs. For instance, you could just save the values list instead of sending it back in the form. Or you could copy the RANDOM-STATE object before you generate the browse results so you can later re-create the same "random" results. But this approach causes its own problems. For instance, you'd then need to worry about when you can get rid of the squirreled-away information; you never know when the user might hit the Back button on their browser to return to an old browse page and then hit the "Add all" button. Welcome to the wonderful world of Web programming.
When you're browsing by :song
, you use the values from the :file
column since they uniquely identify the actual songs while the song names may not.
The Playlist
This brings me to the next URL function, playlist
. This is the most complex page of the three—it's responsible for displaying the current contents of the user's playlist as well as for providing the interface to manipulate the playlist. But with most of the tedious bookkeeping handled by define-url-function
, it's not too hard to see how playlist
works. Here's the beginning of the definition, with just the parameter list:
(define-url-function playlist
(request
(playlist-id string (playlist-id request) :package)
(action keyword) ; Playlist manipulation action
(what keyword :file) ; for :add-songs action
(values base-64-list) ; "
file ; for :add-songs and :delete-songs actions
genre ; for :delete-songs action
artist ; "
album ; "
(order-by keyword) ; for :sort action
(shuffle keyword) ; for :shuffle action
(repeat keyword)) ; for :set-repeat action
In addition to the obligatory request
parameter, playlist
takes a number of query parameters. The most important in some ways is playlist-id
, which identifies which playlist
object the page should display and manipulate. For this parameter, you can take advantage of define-url-function
's "sticky parameter" feature. Normally, the playlist-id
won't be supplied explicitly, defaulting to the value returned by the playlist-id
function, namely, the IP address of the client machine on which the browser is running. However, users can also manipulate their playlists from different machines than the ones running their MP3 clients by allowing this value to be explicitly specified. And if it's specified once, define-url-function
will arrange for it to "stick" by setting a cookie in the browser. Later you'll define a URL function that generates a list of all existing playlists, which users can use to pick a playlist other than the one for the machines they're browsing from.
The action
parameter specifies some action to take on the user's playlist object. The value of this parameter, which will be converted to a keyword symbol for you, can be :add-songs
, :delete-songs
, :clear
, :sort
, :shuffle
, or :set-repeat
. The :add-songs
action is used by the "Add all" button in the browse page and also by the links used to add individual songs. The other actions are used by the links on the playlist page itself.
The file
, what
, and values
parameters are used with the :add-songs
action. By declaring values
to be of type base-64-list
, the define-url-function
infrastructure will take care of decoding the value submitted by the "Add all" form. The other parameters are used with other actions as noted in the comments.
Now let's look at the body of playlist
. The first thing you need to do is use the playlist-id
to look up the queue object and then acquire the playlist's lock with the following two lines:
Интервал:
Закладка:
Похожие книги на «Practical Common Lisp»
Представляем Вашему вниманию похожие книги на «Practical Common Lisp» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.
Обсуждение, отзывы о книге «Practical Common Lisp» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.