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», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.
Интервал:
Закладка:
(defmethod withdraw ((account (eql *account-of-bank-president*)) amount)
(let ((overdraft (- amount (balance account))))
(when (plusp overdraft)
(incf (balance account) (embezzle *bank* overdraft)))
(call-next-method)))
Note, however, that the form in the EQL
specializer that provides the object to specialize on— *account-of-bank-president*
in this case—is evaluated once, when the DEFMETHOD
is evaluated. This method will be specialized on the value of *account-of-bank-president*
at the time the method is defined; changing the variable later won't change the method.
Method Combination
Outside the body of a method, CALL-NEXT-METHOD
has no meaning. Within a method, it's given a meaning by the generic function machinery that builds an effective method each time the generic function is invoked using all the methods applicable to that particular invocation. This notion of building an effective method by combining applicable methods is the heart of the generic function concept and is the thing that allows generic functions to support facilities not found in message-passing systems. So it's worth taking a closer look at what's really happening. Folks with the message-passing model deeply ingrained in their consciousness should pay particular attention because generic functions turn method dispatching inside out compared to message passing, making the generic function, rather than the class, the prime mover.
Conceptually, the effective method is built in three steps: First, the generic function builds a list of applicable methods based on the actual arguments it was passed. Second, the list of applicable methods is sorted according to the specificity of their parameter specializers. Finally, methods are taken in order from the sorted list and their code combined to produce the effective method. [178] While building the effective method sounds time-consuming, quite a bit of the effort in developing fast Common Lisp implementations has gone into making it efficient. One strategy is to cache the effective method so future calls with the same argument types will be able to proceed directly.
To find applicable methods, the generic function compares the actual arguments with the corresponding parameter specializers in each of its methods. A method is applicable if, and only if, all the specializers are compatible with the corresponding arguments.
When the specializer is the name of a class, it's compatible if it names the actual class of the argument or one of its superclasses. (Recall that parameters without explicit specializers are implicitly specialized on the class T
so will be compatible with any argument.) An EQL
specializer is compatible only when the argument is the same object as was specified in the specializer.
Because all the arguments are checked against the corresponding specializers, they all affect whether a method is applicable. Methods that explicitly specialize more than one parameter are called multimethods ; I'll discuss them in the section "Multimethods."
After the applicable methods have been found, the generic function machinery needs to sort them before it can combine them into an effective method. To order two applicable methods, the generic function compares their parameter specializers from left to right, [179] Actually, the order in which specializers are compared is customizable via the DEFGENERIC option :argument-precedence-order , though that option is rarely used.
and the first specializer that's different between the two methods determines their ordering, with the method with the more specific specializer coming first.
Because only applicable methods are being sorted, you know all class specializers will name classes that the corresponding argument is actually an instance of. In the typical case, if two class specializers differ, one will be a subclass of the other. In that case, the specializer naming the subclass is considered more specific. This is why the method that specialized account
on checking-account
was considered more specific than the method that specialized it on bank-account
.
Multiple inheritance slightly complicates the notion of specificity since the actual argument may be an instance of two classes, neither of which is a subclass of the other. If such classes are used as parameter specializers, the generic function can't order them using only the rule that subclasses are more specific than their superclasses. In the next chapter I'll discuss how the notion of specificity is extended to deal with multiple inheritance. For now, suffice it to say that there's a deterministic algorithm for ordering class specializers.
Finally, an EQL
specializer is always more specific than any class specializer, and because only applicable methods are being considered, if more than one method has an EQL
specializer for a particular parameter, they must all have the same EQL
specializer. The comparison of those methods will thus be decided based on other parameters.
The Standard Method Combination
Now that you understand how the applicable methods are found and sorted, you're ready to take a closer look at the last step—how the sorted list of methods is combined into a single effective method. By default, generic functions use what's called the standard method combination . The standard method combination combines methods so that CALL-NEXT-METHOD
works as you've already seen—the most specific method runs first, and each method can pass control to the next most specific method via CALL-NEXT-METHOD
.
However, there's a bit more to it than that. The methods I've been discussing so far are called primary methods . Primary methods, as their name suggests, are responsible for providing the primary implementation of a generic function. The standard method combination also supports three kinds of auxiliary methods: :before
, :after
, and :around
methods. An auxiliary method definition is written with DEFMETHOD
like a primary method but with a method qualifier, which names the type of method, between the name of the method and the parameter list. For instance, a :before
method on withdraw
that specializes the account
parameter on the class bank-account
would start like this:
(defmethod withdraw :before ((account bank-account) amount) ...)
Each kind of auxiliary method is combined into the effective method in a different way. All the applicable :before
methods—not just the most specific—are run as part of the effective method. They run, as their name suggests, before the most specific primary method and are run in most-specific-first order. Thus, :before
methods can be used to do any preparation needed to ensure that the primary method can run. For instance, you could've used a :before
method specialized on checking-account
to implement the overdraft protection on checking accounts like this:
(defmethod withdraw :before ((account checking-account) amount)
(let ((overdraft (- amount (balance account))))
(when (plusp overdraft)
(withdraw (overdraft-account account) overdraft)
Интервал:
Закладка:
Похожие книги на «Practical Common Lisp»
Представляем Вашему вниманию похожие книги на «Practical Common Lisp» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.
Обсуждение, отзывы о книге «Practical Common Lisp» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.