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

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

Интервал:

Закладка:

Сделать

(slot-value *account* 'balance) ==> 1000

Object Initialization

Since you can't do much with an object with unbound slots, it'd be nice to be able to create objects with their slots already initialized. Common Lisp provides three ways to control the initial value of slots. The first two involve adding options to the slot specifier in the DEFCLASS form: with the :initargoption, you can specify a name that can then be used as a keyword parameter to MAKE-INSTANCE and whose argument will be stored in the slot. A second option, :initform, lets you specify a Lisp expression that will be used to compute a value for the slot if no :initargargument is passed to MAKE-INSTANCE . Finally, for complete control over the initialization, you can define a method on the generic function INITIALIZE-INSTANCE , which is called by MAKE-INSTANCE . [185] Another way to affect the values of slots is with the :default-initargs option to DEFCLASS . This option is used to specify forms that will be evaluated to provide arguments for specific initialization parameters that aren't given a value in a particular call to MAKE-INSTANCE . You don't need to worry about :default-initargs for now.

A slot specifier that includes options such as :initargor :initformis written as a list starting with the name of the slot followed by the options. For example, if you want to modify the definition of bank-accountto allow callers of MAKE-INSTANCE to pass the customer name and the initial balance and to provide a default value of zero dollars for the balance, you'd write this:

(defclass bank-account ()

((customer-name

:initarg :customer-name)

(balance

:initarg :balance

:initform 0)))

Now you can create an account and specify the slot values at the same time.

(defparameter *account*

(make-instance 'bank-account :customer-name "John Doe" :balance 1000))

(slot-value *account* 'customer-name) ==> "John Doe"

(slot-value *account* 'balance) ==> 1000

If you don't supply a :balanceargument to MAKE-INSTANCE , the SLOT-VALUE of balancewill be computed by evaluating the form specified with the :initformoption. But if you don't supply a :customer-nameargument, the customer-nameslot will be unbound, and an attempt to read it before you set it will signal an error.

(slot-value (make-instance 'bank-account) 'balance) ==> 0

(slot-value (make-instance 'bank-account) 'customer-name) ==> error

If you want to ensure that the customer name is supplied when the account is created, you can signal an error in the initform since it will be evaluated only if an initarg isn't supplied. You can also use initforms that generate a different value each time they're evaluated—the initform is evaluated anew for each object. To experiment with these techniques, you can modify the customer-nameslot specifier and add a new slot, account-number, that's initialized with the value of an ever-increasing counter.

(defvar *account-numbers* 0)

(defclass bank-account ()

((customer-name

:initarg :customer-name

:initform (error "Must supply a customer name."))

(balance

:initarg :balance

:initform 0)

(account-number

:initform (incf *account-numbers*))))

Most of the time the combination of :initargand :initformoptions will be sufficient to properly initialize an object. However, while an initform can be any Lisp expression, it has no access to the object being initialized, so it can't initialize one slot based on the value of another. For that you need to define a method on the generic function INITIALIZE-INSTANCE .

The primary method on INITIALIZE-INSTANCE specialized on STANDARD-OBJECT takes care of initializing slots based on their :initargand :initformoptions. Since you don't want to disturb that, the most common way to add custom initialization code is to define an :aftermethod specialized on your class. [186] Adding an :after method to INITIALIZE-INSTANCE is the Common Lisp analog to defining a constructor in Java or C++ or an __init__ method in Python. For instance, suppose you want to add a slot account-typethat needs to be set to one of the values :gold, :silver, or :bronzebased on the account's initial balance. You might change your class definition to this, adding the account-typeslot with no options:

(defclass bank-account ()

((customer-name

:initarg :customer-name

:initform (error "Must supply a customer name."))

(balance

:initarg :balance

:initform 0)

(account-number

:initform (incf *account-numbers*))

account-type))

Then you can define an :aftermethod on INITIALIZE-INSTANCE that sets the account-typeslot based on the value that has been stored in the balanceslot. [187] One mistake you might make until you get used to using auxiliary methods is to define a method on INITIALIZE-INSTANCE but without the :after qualifier. If you do that, you'll get a new primary method that shadows the default one. You can remove the unwanted primary method using the functions REMOVE-METHOD and FIND-METHOD . Certain development environments may provide a graphical user interface to do the same thing. (remove-method #'initialize-instance (find-method #'initialize-instance () (list (find-class 'bank-account))))

(defmethod initialize-instance :after ((account bank-account) &key)

(let ((balance (slot-value account 'balance)))

(setf (slot-value account 'account-type)

(cond

((>= balance 100000) :gold)

((>= balance 50000) :silver)

(t :bronze)))))

The &key in the parameter list is required to keep the method's parameter list congruent with the generic function's—the parameter list specified for the INITIALIZE-INSTANCE generic function includes &key in order to allow individual methods to supply their own keyword parameters but doesn't require any particular ones. Thus, every method must specify &key even if it doesn't specify any &key parameters.

On the other hand, if an INITIALIZE-INSTANCE method specialized on a particular class does specify a &key parameter, that parameter becomes a legal parameter to MAKE-INSTANCE when creating an instance of that class. For instance, if the bank sometimes pays a percentage of the initial balance as a bonus when an account is opened, you could implement that using a method on INITIALIZE-INSTANCE that takes a keyword argument to specify the percentage of the bonus like this:

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Похожие книги на «Practical Common Lisp»

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


Отзывы о книге «Practical Common Lisp»

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

x