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

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

Интервал:

Закладка:

Сделать

Adding and deleting is mostly a question of manipulating the songs-table. The only extra work you have to do is to keep the current-songand current-idxin sync. For instance, whenever the playlist is empty, its current-idxwill be zero, and the current-songwill be the *empty-playlist-song*. If you add a song to an empty playlist, then the index of zero is now in bounds, and you should change the current-songto the newly added song. By the same token, when you've played all the songs in a playlist and current-songis *end-of-playlist-song*, adding a song should cause current-songto be reset. All this really means, though, is that you need to call update-current-if-necessaryat the appropriate points.

Adding songs to a playlist is a bit involved because of the way the Web interface communicates which songs to add. For reasons I'll discuss in the next section, the Web interface code can't just give you a simple set of criteria to use in selecting songs from the database. Instead, it gives you the name of a column and a list of values, and you're supposed to add all the songs from the main database where the given column has a value in the list of values. Thus, to add the right songs, you need to first build a table object containing the desired values, which you can then use with an inquery against the song database. So, add-songslooks like this:

(defun add-songs (playlist column-name values)

(let ((table (make-instance

'table

:schema (extract-schema (list column-name) (schema *mp3s*)))))

(dolist (v values) (insert-row (list column-name v) table))

(do-rows (row (select :from *mp3s* :where (in column-name table)))

(insert-row row (songs-table playlist))))

(update-current-if-necessary playlist))

Deleting songs is a bit simpler; you just need to be able to delete songs from the songs-tablethat match particular criteria—either a particular song or all songs in a particular genre, by a particular artist, or from a particular album. So, you can provide a delete-songsfunction that takes keyword/value pairs, which are used to construct a matching :whereclause you can pass to the delete-rowsdatabase function.

Another complication that arises when deleting songs is that current-idxmay need to change. Assuming the current song isn't one of the ones just deleted, you'd like it to remain the current song. But if songs before it in songs-tableare deleted, it'll be in a different position in the table after the delete. So after a call to delete-rows, you need to look for the row containing the current song and reset current-idx. If the current song has itself been deleted, then, for lack of anything better to do, you can reset current-idxto zero. After updating current-idx, calling update-current-if-necessarywill take care of updating current-song. And if current-idxchanged but still points at the same song, current-songwill be left alone.

(defun delete-songs (playlist &rest names-and-values)

(delete-rows

:from (songs-table playlist)

:where (apply #'matching (songs-table playlist) names-and-values))

(setf (current-idx playlist) (or (position-of-current playlist) 0))

(update-current-if-necessary playlist))

(defun position-of-current (playlist)

(let* ((table (songs-table playlist))

(matcher (matching table :file (file (current-song playlist))))

(pos 0))

(do-rows (row table)

(when (funcall matcher row)

(return-from position-of-current pos))

(incf pos))))

You can also provide a function to completely clear the playlist, which uses delete-all-rowsand doesn't have to worry about finding the current song since it has obviously been deleted. The call to update-current-if-necessarywill take care of setting current-songto NIL .

(defun clear-playlist (playlist)

(delete-all-rows (songs-table playlist))

(setf (current-idx playlist) 0)

(update-current-if-necessary playlist))

Sorting and shuffling the playlist are related in that the playlist is always either sorted or shuffled. The shuffleslot says whether the playlist should be shuffled and if so how. If it's set to :none, then the playlist is ordered according to the value in the orderingslot. When shuffleis :song, the playlist will be randomly permuted. And when it's set to :album, the list of albums is randomly permuted, but the songs within each album are listed in track order. Thus, the sort-playlistfunction, which will be called by the Web interface code whenever the user selects a new ordering, needs to set orderingto the desired ordering and set shuffleto :nonebefore calling order-playlist, which actually does the sort. As in delete-songs, you need to use position-of-currentto reset current-idxto the new location of the current song. However, this time you don't need to call update-current-if-necessarysince you know the current song is still in the table.

(defun sort-playlist (playlist ordering)

(setf (ordering playlist) ordering)

(setf (shuffle playlist) :none)

(order-playlist playlist)

(setf (current-idx playlist) (position-of-current playlist)))

In order-playlist, you can use the database function sort-rowsto actually perform the sort, passing a list of columns to sort by based on the value of ordering.

(defun order-playlist (playlist)

(apply #'sort-rows (songs-table playlist)

(case (ordering playlist)

(:genre '(:genre :album :track))

(:artist '(:artist :album :track))

(:album '(:album :track))

(:song '(:song)))))

The function shuffle-playlist, called by the Web interface code when the user selects a new shuffle mode, works in a similar fashion except it doesn't need to change the value of ordering. Thus, when shuffle-playlistis called with a shuffleof :none, the playlist goes back to being sorted according to the most recent ordering. Shuffling by songs is simple—just call shuffle-tableon songs-table. Shuffling by albums is a bit more involved but still not rocket science.

(defun shuffle-playlist (playlist shuffle)

(setf (shuffle playlist) shuffle)

(case shuffle

(:none (order-playlist playlist))

(:song (shuffle-by-song playlist))

(:album (shuffle-by-album playlist)))

(setf (current-idx playlist) (position-of-current playlist)))

(defun shuffle-by-song (playlist)

(shuffle-table (songs-table playlist)))

(defun shuffle-by-album (playlist)

(let ((new-table (make-playlist-table)))

(do-rows (album-row (shuffled-album-names playlist))

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

Интервал:

Закладка:

Сделать

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

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


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

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

x