-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathchapter10.html
271 lines (235 loc) · 15.8 KB
/
chapter10.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head>
<META http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Successful Lisp - Chapter 10</title>
</head>
<body bgcolor="white" text="black">
<h1>Глава 10 - Как найти свой путь,
Часть 1</h1>
<p>В этой главе вы узнаете, как найти свой путь по Common Lisp,
не прибегая так часто к руководствам. (Вы ведь читаете прекрасные
руководства, не так ли?)
<p>О, Есть одна вещь, которую вы должны иметь в виду, читая эту главу:
все эти инструменты одинаково хорошо работают для встроенных функций
вашей системы Lisp и для всех программ Lisp, которые вы пишете.
<h2>APROPOS: Я не помню имя, но узнаю по лицу</h2>
<p>Common Lisp определяет 978 символов. Любая используемая вами реализация,
вероятно, определяет сотни дополнительных символов для расширений языка,
дополнительных библиотек, графического пользовательского интерфейса и т. д.
Вы собираетесь запомнить названия всех этих символов? Вряд ли...
<p>Что вы <em>можете</em> сделать, так это запомнить часть имени.
Это довольно легко, потому что разработчики языков и библиотек имеют
ограниченную память (как и мы с вами), и они склонны называть связанные
объекты похожими именами. Таким образом, большинство функций (см.
<a href="chapter12.html">Главу 12</a>) будут иметь <code>MAP</code>
в своих именах, библиотека графического интерфейса, вероятно,
будет иметь <code>WINDOW</code> в именах всех функций, макросов и
переменных, имеющих какое-то отношение к windows, и так далее.
<p>Как только вы хорошо угадаете часть имени, вы можете найти все
совпадающие имена с помощью очень удобного инструмента
<code>APROPOS</code>.
<pre>
? (apropos "MAP" :cl)
MAP, Def: FUNCTION
MAP-INTO, Def: FUNCTION
MAPC, Def: FUNCTION
MAPCAN, Def: FUNCTION
MAPCAR, Def: FUNCTION
MAPCON, Def: FUNCTION
MAPHASH, Def: FUNCTION
MAPL, Def: FUNCTION
MAPLIST, Def: FUNCTION
</pre>
<p>
<code>APROPOS</code> ожидает строку или символ - это фрагмент имени,
который вы хотели бы найти. Необязательный второй аргумент обозначает
пакет; используйте его, если вы хотите ограничить поиск символами в
определенном пакете. Обозначение пакета может быть строкой или символом,
соответствующим имени или псевдониму пакета (см.
<a href="chapter03-10.html">Главу 3, Урок 10</a>)), или же это может быть
сам объект пакета. Если вы опустите обозначение пакета, то
<code>APROPOS</code> будет искать символы во всех пакетах.
<p>Ваша реализация Lisp может выдавать выходные данные, которые выглядят
несколько иначе, чем показано здесь. Как правило, вы увидите имена символов,
перечисленные с очень кратким описанием глобального объекта,
именуемого символом.
<p>Вот пример вывода из <code>APROPOS</code> в моей системе Lisp,
когда я выполняю поиск без обозначения пакета:
<pre>
? (apropos "SEQUENCE")
TOOLS::BROWSER-SEQUENCE-TABLE
CCL::CHECK-SEQUENCE-BOUNDS, Def: FUNCTION
ITERATE::CHECK-SEQUENCE-KEYWORDS, Def: FUNCTION
TOOLS::CLASS-BROWSER-SEQUENCE-TABLE
ITERATE::CLAUSE-FOR-IN-SEQUENCE-0, Def: FUNCTION
ITERATE::CLAUSE-FOR-INDEX-OF-SEQUENCE-0, Def: FUNCTION
CCL::CONSED-SEQUENCE
<i>; many lines omitted</i>
STREAM-READ-SEQUENCE, Def: STANDARD-GENERIC-FUNCTION
STREAM-WRITE-SEQUENCE, Def: STANDARD-GENERIC-FUNCTION
DEFSYSTEM::SYSTEMS-SEQUENCE-DIALOG-ITEM
TAB-SEQUENCE-ITEM
TABLE-SEQUENCE, Def: STANDARD-GENERIC-FUNCTION
:TABLE-SEQUENCE, Value: :TABLE-SEQUENCE
SETF::|CCL::TABLE-SEQUENCE|, Def: STANDARD-GENERIC-FUNCTION
WRITE-SEQUENCE, Def: FUNCTION
</pre>
<p>Обратите внимание, что большинство символов имеют префикс
с именем пакета, так как они не импортируются в текущий пакет
(COMMON-LISP-USER). Опять же, ваша реализация Lisp может дать
несколько иные результаты, но она должна показать вам список
символов с префиксами пакетов, а также любую другую информацию,
которую разработчики вашей реализации посчитали бы полезной,
но краткой.
<p>В этих примерах я использовал прописные строки в качестве аргументов
для <code>APROPOS</code>. Некоторые реализации выполняют сопоставление
с учетом регистра, в то время как другие игнорируют регистр. Имена символов
в Lisp чувствительны к регистру, но программа чтения Lisp по умолчанию
переводит символы в верхний регистр. Поэтому, если вы укажете
<code>APROPOS</code> имя в верхнем регистре, вы найдете большинство,
а возможно и все-совпадающие имена; вы пропустите только те, которые были
намеренно интернированы с использованием строчных букв. А если ваш
<code>APROPOS</code> игнорирует регистр, то получите все совпадения,
независимо от регистра.
<p>Вы можете также предоставить символ для <code>APROPOS</code>.
Единственным недостатком этого является то, что эти частные символы
загрязняют пространство имен текущего пакета. Требование к хранилищу
является тривиальным, но вы должны знать, что <code>APROPOS</code>
может найти эти частные символы в будущих поисках, и вам придется
игнорировать их, чтобы найти символы, которые вы действительно
хотели бы видеть.
<h2>DESCRIBE: Расскажи мне больше о себе</h2>
<p>Как только вы узнаете имя символа, вы можете получить дополнительную
информацию, используя функцию <code>DESCRIBE</code>. Как и в случае с
<code>APROPOS</code>, выходные данные описания варьируются в зависимости
от реализаций Lisp. Вот пример, созданный с помощью моей системы Lisp:
<pre>
<i>; Describe a symbol</i>
? (describe 'length)
Symbol: LENGTH
Function
EXTERNAL in package: #<Package "COMMON-LISP">
Print name: "LENGTH"
Value: #<Unbound>
Function: #<Compiled-function LENGTH #x34C39B6>
Arglist: (SEQUENCE)
Plist: (:ANSI-CL-URL "fun_length.html")
<i>; Describe a string</i>
? (describe "LENGTH")
"LENGTH"
Type: (SIMPLE-BASE-STRING 6)
Class: #<BUILT-IN-CLASS SIMPLE-BASE-STRING>
Length: 6
0: #\L
1: #\E
2: #\N
3: #\G
4: #\T
5: #\H
<i>; Describe a function</i>
? (describe #'length)
#<Compiled-function LENGTH #x34C39B6>
Name: LENGTH
Arglist (declaration): (SEQUENCE)
</pre>
<p>В этом примере использовались три различных типа аргументов:
символ, строка и функция. Все это верно, но вы получаете то,
о чем просите. Все они имеют свое применение, но вы, как правило,
хотите предоставить аргумент символа для <code>DESCRIBE</code>,
потому что он, как правило, производит больше всего информации.
<h2>INSPECT: Откройте шире(рот) и скажите "Ah..."</h2>
<p><code>INSPECT</code> подобен <code>DESCRIBE</code>,
но вместо печати информации он представляет ее в виде
некоторого интерактивного дисплея; обычно это либо командный цикл
в текущем прослушивателе(listener), либо новое окно с собственным
пользовательским интерфейсом. Вы должны поэкспериментировать с
<code>INSPECT</code> на вашей собственной системе Lisp,
чтобы узнать, как она себя ведет.
<p><code>INSPECT</code> очень удобен для изучения сложных вложенных
структур данных, так как вы можете "детализировать" только ту информацию,
которая вас интересует в данный момент. Большинство <code>INSPECT</code>-ов
предлагают специализированные средства просмотра для определенных типов
данных, таких как функции и объекты CLOS. Многие реализации <code>INSPECT</code>
позволяют вам редактировать проверяемые данные.
<h2>DOCUMENTATION: Я знаю, что где-то это записал</h2>
<p>Иногда вам нужно знать о переменной больше, чем вы можете обнаружить с
помощью <code>INSPECT</code>. А для функций вам действительно нужно
описание программиста (Если вы не хотите читать код на ассемблере,
см. <a href="chapter16.html">Главу 16</a>, Если у вас есть такие потребности).
Функция <code>DOCUMENTATION</code> дает вам доступ к самым сокровенным мыслям
программиста (или, по крайней мере, к тому, что он хотел написать в строке
документации).
<p>Функция <code>DOCUMENTATION</code> ожидает два аргумента.
Первый-это объект, для которого вы хотите получить документацию,
или символ, обозначающий этот объект. Второй-это символ,
обозначающий вид документации (их несколько), которую вы
хотите получить.
<blockquote>
Интерфейс, описанный выше, является тем, который требуется
спецификацией ANSI Common Lisp. Некоторые реализации все еще
поддерживают интерфейс, который предшествует спецификации ANSI
- они ожидают символ для обоих аргументов. Мы будем использовать
это соглашение в наших примерах, так как оно работает как в ANSI,
так и в предыдущих реализациях ANSI.
</blockquote>
<p>Несколько конструкций Lisp позволяют предоставить дополнительную
строку документации. В следующей таблице показан второй аргумент
<code>DOCUMENTATION</code> (первая строка каждой пары) вместе с
конструкциями Lisp, для которых извлекаются строки документации.
<dl>
<dt><code>'variable</code>
<dd><code>defvar</code>, <code>defparameter</code>, <code>defconstant</code>
<dt><code>'function</code>
<dd><code>defun</code>, <code>defmacro</code>, special forms
<dt><code>'structure</code>
<dd><code>defstruct</code>
<dt><code>'type</code>
<dd><code>deftype</code>
<dt><code>'setf</code>
<dd><code>defsetf</code>
</dl>
<p>Приведенный выше перечень работ в ANSI и пред-ANSI реализаций Лиспа.
В следующем списке показаны типы документации, которые были добавлены
для реализаций ANSI.
<dl>
<dt><code>'compiler-macro</code>
<dd><code>define-compiler-macro</code>
<dt><code>'method-combination</code>
<dd><code>define-method-combination</code>
<dt><code>t</code>
<dd>Возвращаемая документация зависит от типа первого аргумента.
</dl>
<p>Вот несколько примеров:
<pre>
? (documentation 'length 'function)
"returns the number of elements in sequence."
? (defun a-function-with-docstring ()
"This function always returns T."
t)
A-FUNCTION-WITH-DOCSTRING
? (documentation 'a-function-with-docstring 'function)
"This function always returns T."
</pre>
<p>Если вы укажете символ, для которого нет документации,
или тип документации, которая не определенна для символа,
то <code>DOCUMENTATION</code> вернет <code>NIL</code>.
<p>Реализация Lisp позволяет отбрасывать строки документации.
Если строки документации из вашей собственной программы недоступны
через функцию <code>DOCUMENTATION</code>, обратитесь к руководству
по реализации, чтобы узнать, есть ли способ сохранить строки документации
(обычно есть). Если строки документации отсутствуют в функциях
Common Lisp или в библиотеках, поставляемых поставщиком,
обратитесь к своему поставщику.
<hr>
<div align="center">
<a href="contents.html">Contents</a> | <a href="cover.html">Cover</a> <br>
<a href="chapter09.html">Chapter 9</a> | Chapter 10 | <a href="chapter11.html">Chapter 11</a>
</div>
<hr>
<address>
Copyright © 1995-2001, David B. Lamkins<br>
All Rights Reserved Worldwide<br>
<br>
This book may not be reproduced without the written consent of its author. Online distribution is restricted to the author's site.
</address>
</body> </html>