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», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.
Интервал:
Закладка:
The Lisp Way
Common Lisp's error handling system gives you a way out of this conundrum by letting you separate the code that actually recovers from an error from the code that decides how to recover. Thus, you can put recovery code in low-level functions without committing to actually using any particular recovery strategy, leaving that decision to code in high-level functions.
To get a sense of how this works, let's suppose you're writing an application that reads some sort of textual log file, such as a Web server's log. Somewhere in your application you'll have a function to parse the individual log entries. Let's assume you'll write a function, parse-log-entry
, that will be passed a string containing the text of a single log entry and that is supposed to return a log-entry
object representing the entry. This function will be called from a function, parse-log-file
, that reads a complete log file and returns a list of objects representing all the entries in the file.
To keep things simple, the parse-log-entry
function will not be required to parse incorrectly formatted entries. It will, however, be able to detect when its input is malformed. But what should it do when it detects bad input? In C you'd return a special value to indicate there was a problem. In Java or Python you'd throw or raise an exception. In Common Lisp, you signal a condition.
Conditions
A condition is an object whose class indicates the general nature of the condition and whose instance data carries information about the details of the particular circumstances that lead to the condition being signaled. [203] In this respect, a condition is a lot like an exception in Java or Python except not all conditions represent an error or exceptional situation.
In this hypothetical log analysis program, you might define a condition class, malformed-log-entry-error
, that parse-log-entry
will signal if it's given data it can't parse.
Condition classes are defined with the DEFINE-CONDITION
macro, which works essentially the same as DEFCLASS
except that the default superclass of classes defined with DEFINE-CONDITION
is CONDITION
rather than STANDARD-OBJECT
. Slots are specified in the same way, and condition classes can singly and multiply inherit from other classes that descend from CONDITION
. But for historical reasons, condition classes aren't required to be instances of STANDARD-OBJECT
, so some of the functions you use with DEFCLASS
ed classes aren't required to work with conditions. In particular, a condition's slots can't be accessed using SLOT-VALUE
; you must specify either a :reader
option or an :accessor
option for any slot whose value you intend to use. Likewise, new condition objects are created with MAKE-CONDITION
rather than MAKE-INSTANCE
. MAKE-CONDITION
initializes the slots of the new condition based on the :initarg
s it's passed, but there's no way to further customize a condition's initialization, equivalent to INITIALIZE-INSTANCE
. [204] In some Common Lisp implementations, conditions are defined as subclasses of STANDARD-OBJECT , in which case SLOT-VALUE , MAKE-INSTANCE , and INITIALIZE-INSTANCE will work, but it's not portable to rely on it.
When using the condition system for error handling, you should define your conditions as subclasses of ERROR
, a subclass of CONDITION
. Thus, you might define malformed-log-entry-error
, with a slot to hold the argument that was passed to parse-log-entry
, like this:
(define-condition malformed-log-entry-error (error)
((text :initarg :text :reader text)))
Condition Handlers
In parse-log-entry
you'll signal a malformed-log-entry-error
if you can't parse the log entry. You signal errors with the function ERROR
, which calls the lower-level function SIGNAL
and drops into the debugger if the condition isn't handled. You can call ERROR
two ways: you can pass it an already instantiated condition object, or you can pass it the name of the condition class and any initargs needed to construct a new condition, and it will instantiate the condition for you. The former is occasionally useful for resignaling an existing condition object, but the latter is more concise. Thus, you could write parse-log-entry
like this, eliding the details of actually parsing a log entry:
(defun parse-log-entry (text)
(if (well-formed-log-entry-p text)
(make-instance 'log-entry ...)
(error 'malformed-log-entry-error :text text)))
What happens when the error is signaled depends on the code above parse-log-entry
on the call stack. To avoid landing in the debugger, you must establish a condition handler in one of the functions leading to the call to parse-log-entry
. When a condition is signaled, the signaling machinery looks through a list of active condition handlers, looking for a handler that can handle the condition being signaled based on the condition's class. Each condition handler consists of a type specifier indicating what types of conditions it can handle and a function that takes a single argument, the condition. At any given moment there can be many active condition handlers established at various levels of the call stack. When a condition is signaled, the signaling machinery finds the most recently established handler whose type specifier is compatible with the condition being signaled and calls its function, passing it the condition object.
The handler function can then choose whether to handle the condition. The function can decline to handle the condition by simply returning normally, in which case control returns to the SIGNAL
function, which will search for the next most recently established handler with a compatible type specifier. To handle the condition, the function must transfer control out of SIGNAL
via a nonlocal exit . In the next section, you'll see how a handler can choose where to transfer control. However, many condition handlers simply want to unwind the stack to the place where they were established and then run some code. The macro HANDLER-CASE
establishes this kind of condition handler. The basic form of a HANDLER-CASE
is as follows:
(handler-case expression
error-clause *)
where each error-clause is of the following form:
( condition-type ([ var ]) code )
If the expression returns normally, then its value is returned by the HANDLER-CASE
. The body of a HANDLER-CASE
must be a single expression; you can use PROGN
to combine several expressions into a single form. If, however, the expression signals a condition that's an instance of any of the condition-type s specified in any error-clause , then the code in the appropriate error clause is executed and its value returned by the HANDLER-CASE
. The var , if included, is the name of the variable that will hold the condition object when the handler code is executed. If the code doesn't need to access the condition object, you can omit the variable name.
Интервал:
Закладка:
Похожие книги на «Practical Common Lisp»
Представляем Вашему вниманию похожие книги на «Practical Common Lisp» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.
Обсуждение, отзывы о книге «Practical Common Lisp» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.