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», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.
Интервал:
Закладка:
(balance
:initarg :balance
:initform 0
:reader balance)
The :writer
option is used to create a generic function and method for setting the value of a slot. The function and method created follow the requirements for a SETF
function, taking the new value as the first argument and returning it as the result, so you can define a SETF
function by providing a name such as (setf customer-name)
. For instance, you could provide reader and writer methods for customer-name
equivalent to the ones you just wrote by changing the slot specifier to this:
(customer-name
:initarg :customer-name
:initform (error "Must supply a customer name.")
:reader customer-name
:writer (setf customer-name))
Since it's quite common to want both reader and writer functions, DEFCLASS
also provides an option, :accessor
, that creates both a reader function and the corresponding SETF
function. So instead of the slot specifier just shown, you'd typically write this:
(customer-name
:initarg :customer-name
:initform (error "Must supply a customer name.")
:accessor customer-name)
Finally, one last slot option you should know about is the :documentation
option, which you can use to provide a string that documents the purpose of the slot. Putting it all together and adding a reader method for the account-number
and account-type
slots, the DEFCLASS
form for the bank-account
class would look like this:
(defclass bank-account ()
((customer-name
:initarg :customer-name
:initform (error "Must supply a customer name.")
:accessor customer-name
:documentation "Customer's name")
(balance
:initarg :balance
:initform 0
:reader balance
:documentation "Current account balance")
(account-number
:initform (incf *account-numbers*)
:reader account-number
:documentation "Account number, unique within a bank.")
(account-type
:reader account-type
:documentation "Type of account, one of :gold, :silver, or :bronze.")))
WITH-SLOTS and WITH-ACCESSORS
While using accessor functions will make your code easier to maintain, they can still be a bit verbose. And there will be times, when writing methods that implement the low-level behaviors of a class, that you may specifically want to access slots directly to set a slot that has no writer function or to get at the slot value without causing any auxiliary methods defined on the reader function to run.
This is what SLOT-VALUE
is for; however, it's still quite verbose. To make matters worse, a function or method that accesses the same slot several times can become clogged with calls to accessor functions and SLOT-VALUE
. For example, even a fairly simple method such as the following, which assesses a penalty on a bank-account
if its balance falls below a certain minimum, is cluttered with calls to balance
and SLOT-VALUE
:
(defmethod assess-low-balance-penalty ((account bank-account))
(when (< (balance account) *minimum-balance*)
(decf (slot-value account 'balance) (* (balance account) .01))))
And if you decide you want to directly access the slot value in order to avoid running auxiliary methods, it gets even more cluttered.
(defmethod assess-low-balance-penalty ((account bank-account))
(when (< (slot-value account 'balance) *minimum-balance*)
(decf (slot-value account 'balance) (* (slot-value account 'balance) .01))))
Two standard macros, WITH-SLOTS
and WITH-ACCESSORS
, can help tidy up this clutter. Both macros create a block of code in which simple variable names can be used to refer to slots on a particular object. WITH-SLOTS
provides direct access to the slots, as if by SLOT-VALUE
, while WITH-ACCESSORS
provides a shorthand for accessor methods.
The basic form of WITH-SLOTS
is as follows:
(with-slots ( slot *) instance-form
body-form *)
Each element of slots can be either the name of a slot, which is also used as a variable name, or a two-item list where the first item is a name to use as a variable and the second is the name of the slot. The instance-form is evaluated once to produce the object whose slots will be accessed. Within the body, each occurrence of one of the variable names is translated to a call to SLOT-VALUE
with the object and the appropriate slot name as arguments. [190] The "variable" names provided by WITH-SLOTS and WITH-ACCESSORS aren't true variables; they're implemented using a special kind of macro, called a symbol macro , that allows a simple name to expand into arbitrary code. Symbol macros were introduced into the language to support WITH-SLOTS and WITH-ACCESSORS , but you can also use them for your own purposes. I'll discuss them in a bit more detail in Chapter 20.
Thus, you can write assess-low-balance-penalty
like this:
(defmethod assess-low-balance-penalty ((account bank-account))
(with-slots (balance) account
(when (< balance *minimum-balance*)
(decf balance (* balance .01)))))
or, using the two-item list form, like this:
(defmethod assess-low-balance-penalty ((account bank-account))
(with-slots ((bal balance)) account
(when (< bal *minimum-balance*)
(decf bal (* bal .01)))))
If you had defined balance
with an :accessor
rather than just a :reader
, then you could also use WITH-ACCESSORS
. The form of WITH-ACCESSORS
is the same as WITH-SLOTS
except each element of the slot list is a two-item list containing a variable name and the name of an accessor function. Within the body of WITH-ACCESSORS
, a reference to one of the variables is equivalent to a call to the corresponding accessor function. If the accessor function is SETF
able, then so is the variable.
(defmethod assess-low-balance-penalty ((account bank-account))
(with-accessors ((balance balance)) account
(when (< balance *minimum-balance*)
(decf balance (* balance .01)))))
The first balance
is the name of the variable, and the second is the name of the accessor function; they don't have to be the same. You could, for instance, write a method to merge two accounts using two calls to WITH-ACCESSORS
, one for each account.
(defmethod merge-accounts ((account1 bank-account) (account2 bank-account))
(with-accessors ((balance1 balance)) account1
Интервал:
Закладка:
Похожие книги на «Practical Common Lisp»
Представляем Вашему вниманию похожие книги на «Practical Common Lisp» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.
Обсуждение, отзывы о книге «Practical Common Lisp» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.