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 first generic function will be withdraw
, which decreases the account balance by a specified amount. If the balance is less than the amount, it should signal an error and leave the balance unchanged. You can start by defining the generic function with DEFGENERIC
.
The basic form of DEFGENERIC
is similar to DEFUN
except with no body. The parameter list of DEFGENERIC
specifies the parameters that must be accepted by all the methods that will be defined on the generic function. In the place of the body, a DEFGENERIC
can contain various options. One option you should always include is :documentation
, which you use to provide a string describing the purpose of the generic function. Because a generic function is purely abstract, it's important to be clear to both users and implementers what it's for. Thus, you might define withdraw
like this:
(defgeneric withdraw (account amount)
(:documentation "Withdraw the specified amount from the account.
Signal an error if the current balance is less than amount."))
DEFMETHOD
Now you're ready to use DEFMETHOD
to define methods that implement withdraw
. [175] Technically you could skip the DEFGENERIC altogether—if you define a method with DEFMETHOD and no such generic function has been defined, one is automatically created. But it's good form to define generic functions explicitly, if only because it gives you a good place to document the intended behavior.
A method's parameter list must be congruent with its generic function's. In this case, that means all methods defined on withdraw
must have exactly two required parameters. More generally, methods must have the same number of required and optional parameters and must be capable of accepting any arguments corresponding to any &rest
or &key
parameters specified by the generic function. [176] A method can "accept" &key and &rest arguments defined in its generic function by having a &rest parameter, by having the same &key parameters, or by specifying &allow-other-keys along with &key . A method can also specify &key parameters not found in the generic function's parameter list—when the generic function is called, any &key parameter specified by the generic function or any applicable method will be accepted.
Since the basics of withdrawing are the same for all accounts, you can define a method that specializes the account
parameter on the bank-account
class. You can assume the function balance
returns the current balance of the account and can be used with SETF
—and thus with DECF
—to set the balance. The function ERROR
is a standard function used to signal an error, which I'll discuss in greater detail in Chapter 19. Using those two functions, you can define a basic withdraw
method that looks like this:
(defmethod withdraw ((account bank-account) amount)
(when (< (balance account) amount)
(error "Account overdrawn."))
(decf (balance account) amount))
As this code suggests, the form of DEFMETHOD
is even more like that of DEFUN
than DEFGENERIC
's is. The only difference is that the required parameters can be specialized by replacing the parameter name with a two-element list. The first element is the name of the parameter, and the second element is the specializer, either the name of a class or an EQL
specializer, the form of which I'll discuss in a moment. The parameter name can be anything—it doesn't have to match the name used in the generic function, though it often will.
This method will apply whenever the first argument to withdraw
is an instance of bank-account
. The second parameter, amount
, is implicitly specialized on T
, and since all objects are instances of T
, it doesn't affect the applicability of the method.
Now suppose all checking accounts have overdraft protection. That is, each checking account is linked to another bank account that's drawn upon when the balance of the checking account itself can't cover a withdrawal. You can assume that the function overdraft-account
takes a checking-account
object and returns a bank-account
object representing the linked account.
Thus, withdrawing from a checking-account
object requires a few extra steps compared to withdrawing from a standard bank-account
object. You must first check whether the amount being withdrawn is greater than the account's current balance and, if it is, transfer the difference from the overdraft account. Then you can proceed as with a standard bank-account
object.
So what you'd like to do is define a method on withdraw
that specializes on checking-account
to handle the transfer and then lets the method specialized on bank-account
take control. Such a method might look like this:
(defmethod withdraw ((account checking-account) amount)
(let ((overdraft (- amount (balance account))))
(when (plusp overdraft)
(withdraw (overdraft-account account) overdraft)
(incf (balance account) overdraft)))
(call-next-method))
The function CALL-NEXT-METHOD
is part of the generic function machinery used to combine applicable methods. It indicates that control should be passed from this method to the method specialized on bank-account
. [177] CALL-NEXT-METHOD is roughly analogous to invoking a method on super in Java or using an explicitly class-qualified method or function name in Python or C++.
When it's called with no arguments, as it is here, the next method is invoked with whatever arguments were originally passed to the generic function. It can also be called with arguments, which will then be passed onto the next method.
You aren't required to invoke CALL-NEXT-METHOD
in every method. However, if you don't, the new method is then responsible for completely implementing the desired behavior of the generic function. For example, if you had a subclass of bank-account
, proxy-account
, that didn't actually keep track of its own balance but instead delegated withdrawals to another account, you might write a method like this (assuming a function, proxied-account
, that returns the proxied account):
(defmethod withdraw ((proxy proxy-account) amount)
(withdraw (proxied-account proxy) amount))
Finally, DEFMETHOD
also allows you to create methods specialized on a particular object with an EQL
specializer. For example, suppose the banking app is going to be deployed in a particularly corrupt bank. Suppose the variable *account-of-bank-president*
holds a reference to a particular bank account that belongs—as the name suggests—to the bank's president. Further suppose the variable *bank*
represents the bank as a whole, and the function embezzle
steals money from the bank. The bank president might ask you to "fix" withdraw
to handle his account specially.
Интервал:
Закладка:
Похожие книги на «Practical Common Lisp»
Представляем Вашему вниманию похожие книги на «Practical Common Lisp» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.
Обсуждение, отзывы о книге «Practical Common Lisp» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.