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

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

Интервал:

Закладка:

Сделать

(balance

:initarg :balance

:initform 0

:reader balance)

The :writeroption 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-nameequivalent 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 :documentationoption, 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-numberand account-typeslots, the DEFCLASS form for the bank-accountclass 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-accountif its balance falls below a certain minimum, is cluttered with calls to balanceand 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-penaltylike 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 balancewith an :accessorrather 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 balanceis 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»

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

x