-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathloop.tex
2751 lines (2303 loc) · 115 KB
/
loop.tex
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
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
%%%Chapter of Common Lisp Manual. Copyright 1989 Guy L. Steele Jr.
%%% Based on ANSI X3J13 document X3J13/89-004 which in turn is
%%% based on documentation by Lucid, Inc.
\clearpage\def\pagestatus{FINAL PROOF}
\chapter{Loop}
\label{LOOP}
\chapter{Цикл loop}
\label{LOOP}
Author: Jon L White
Автор: Jon L White
\begin{new}
\prefaceword
X3J13 voted in January 1989
\issue{LOOP-FACILITY}
to adopt an extended definition of the \cdf{loop} macro
as a part of the forthcoming draft Common Lisp standard.
\end{new}
This chapter presents the bulk of the Common Lisp
Loop Facility proposal, written by Jon L White. I have
edited it only very lightly
to conform to the overall style of this book and have inserted a small
number of bracketed remarks, identified by the initials GLS.
(See the Acknowledgments to this second edition for
acknowledgments to others who contributed to the Loop Facility proposal.)
Guy L. Steele Jr.
\section{Introduction}
\section{Введение}
A \emph{loop\/} is a series of expressions that are executed one or more times,
a process known as \emph{iteration}.
The \emph{Loop Facility\/} defines a
variety of useful methods, indicated by
\emph{loop keywords}, to iterate and to
accumulate values in a loop.
\emph{Цикл} представляет собой группу выражений, которые выполняются
один или более раз, такой процесс известен как \emph{итерация}.
Цикл \emph{Loop} включает в себя различную функциональность, которая
обозначается \emph{ключевыми символами loop}, для итерации и для
накопления значений в цикле.
Loop keywords are not true Common Lisp keywords; they are symbols that
are recognized by the Loop Facility and that provide such capabilities
as controlling the direction of iteration, accumulating values inside
the body of a loop, and evaluating expressions that precede or follow
the loop body. If you do not use any loop keywords, the Loop Facility
simply executes the loop body repeatedly.
Ключевые символы \emph{loop} это не те ключевые символы Common
Lisp'а. Они являются просто символами, которые имеют специальное
значение в теле этой формы. Символы указывают на: направление
итерации, накопление значения внутри тела, на действия для выполнения
в начале/конце цикла. Если вы не используете эти ключевые символы, то
\cdf{loop} просто циклически выполняет тело.
\section{How the Loop Facility Works}
\section{Как работает Loop}
The driving element of the Loop Facility is the \cdf{loop} macro.
When Lisp encounters a \cdf{loop} macro call
form, it invokes the Loop Facility and passes to it the loop clauses
as a list of unevaluated forms, as with any macro.
The loop clauses contain Common Lisp forms and loop keywords. The
loop keywords are recognized by their symbol name, regardless of the
packages that contain them. The \cdf{loop} macro translates the
given form into Common Lisp code and returns the expanded form.
Главным элементом Loop является макрос \cdf{loop}. Как только Common
Lisp видит вызов макроса \cdf{loop}, он разворачивает его без
вычисления аргументов, что собственно происходит и с любым другим
макросом. Loop содержит формы и ключевые символы. Ключевые символы
обозначаются символами не обращая внимание на их принадлежность к
пакету. Макрос \cdf{loop} транслирует полученную форму в Common
Lisp'овый код и возвращает развёрнутую форму.
The expanded loop form is one or more lambda-expressions for the local
binding of loop variables and a block and a tagbody that express a
looping control structure. The variables established in the loop
construct are bound as if by using \cdf{let} or \cdf{lambda}.
Implementations can interleave the setting of initial values with the
bindings. However, the assignment of the initial values is always
calculated in the order specified by the user. A variable is thus
sometimes bound to a harmless value of the correct data type, and then
later in the prologue it is set to the true initial value by using
\cdf{setq}.
Развернутая форма представляется собой одно или более лямбда-выражений
для связываний переменных цикла и формы block или tagbody, которые
содержат тело цикла. Переменные для цикла создаются как если бы с
помощью \cdf{let} или \cdf{lambda}. Связывание локальных переменных
происходит в том порядке, в каком указал пользователь.
The expanded form consists of three basic parts in the tagbody:
Развёрнутая форма состоит из трёх основных частей в tagbody:
\begin{itemize}
\item
The \emph{loop prologue\/} contains forms that are executed before iteration begins,
such as initial settings of loop variables and possibly an initial
termination test.
\item \emph{Пролог} содержит формы, которые вычисляется перед началом
итераций, например, первоначальные связывания переменных цикла и
возможно первая проверка на завершение цикла.
\item
The \emph{loop body\/} contains those forms that are executed during iteration,
including application-specific calculations, termination tests,
and variable stepping. \emph{Stepping\/} is the process of assigning a
variable the next item in a series of items.
\item \emph{Тело} содержит формы, которые вычисляются на каждом шаге
цикла, включая непосредственно пользовательские операции, проверки
завершения цикла, и пошаговое изменение переменных
цикла. \emph{Пошаговое изменение} это присваивание переменное
следующего значения из последовательности значений.
\item
The \emph{loop epilogue} contains forms that are executed after iteration
terminates,
such as code to return values from the loop.
\item \emph{Эпилог} содержит формы, которые вычисляются после
завершения цикла, например, форма возврата значений из цикла.
\end{itemize}
Expansion of the \cdf{loop} macro produces an implicit block
(named \cdf{nil}).
Thus, the Common Lisp macro \cdf{return} and the special operator
\cdf{return-from} can be
used to return values from a loop or to exit a loop.
Раскрытие макроса \cdf{loop} порождает неявный block (с именем
\cdf{nil}). Таким образом, внутри цикла для возврата значений или
выхода можно пользоваться макросом \cdf{return} или специальным
оператором \cdf{return-from}.
Within the executable parts of loop clauses and around the entire loop
form, you can still bind variables by using the Common Lisp special
operator \cdf{let}.
В любой части выражения цикла можно использовать обычную конструкцию
связывания переменных \cdf{let}.
\section{Parsing Loop Clauses}
\section{Парсинг выражений Loop}
The syntactic parts of a loop construct are called \emph{clauses}; the
scope of each clause is determined by the top-level parsing of that
clause's keyword. The following example shows a loop construct with
six clauses:
Синтаксические части конструкции loop называются
\emph{выражениями}. Область действия каждого выражения определяется
парсером данного типа выражения. Следующий пример показывает loop с
шестью выражениями:
\begin{lisp} (loop for i from 1 to (compute-top-value)~~~~~~~~~;\textrm{First clause} \\*
~~~~~~while (not (unacceptable i))~~~~~~~~~~~~~~~~;\textrm{Second clause} \\*
~~~~~~collect (square i)~~~~~~~~~~~~~~~~~~~~~~~~~~;\textrm{Third clause} \\*
~~~~~~do (format t "Working on {\Xtilde}D now" i)~~~~~~~~~;\textrm{Fourth clause} \\*
~~~~~~when (evenp i)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;\textrm{Fifth clause} \\*
~~~~~~~~do (format t "{\Xtilde}D is a non-odd number" i) \\*
~~~~~~finally (format t "About to exit!"))~~~~~~~~;\textrm{Sixth clause}
\end{lisp}
\begin{lisp} (loop for i from 1 to (compute-top-value)~~~~~~~~~;\textrm{Первое выражение} \\*
~~~~~~while (not (unacceptable i))~~~~~~~~~~~~~~~~;\textrm{Второе} \\*
~~~~~~collect (square i)~~~~~~~~~~~~~~~~~~~~~~~~~~;\textrm{Третье} \\*
~~~~~~do (format t "Обрабтка {\Xtilde}D " i)~~~~~~~~~;\textrm{Четвёртое} \\*
~~~~~~when (evenp i)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;\textrm{Пятое} \\*
~~~~~~~~do (format t "{\Xtilde}D чётное" i) \\*
~~~~~~finally (format t "Почти у выхода!"))~~~~~~~~;\textrm{Шестое}
\end{lisp}
Each loop keyword introduces either a compound loop clause or a simple
loop clause that can consist of a loop keyword followed by a single
Lisp form. The number of forms in a clause is determined by the loop
keyword that begins the clause and by the auxiliary keywords in the
clause. The keywords \cdf{do}, \cdf{initially}, and \cdf{finally} are
the only loop keywords that can take any number of Lisp forms and
group them as if in a single \cdf{progn} form.
Каждое ключевое слово представляет или составное выражение, или
простое выражение, которое может состоять из этого ключевого слова и
одиночное Lisp'овой формы. Количество форм в выражении определяется
первым ключевым символом или вспомогательными ключевыми символами в
выражении. Только такие ключевые символы, как \cdf{do},
\cdf{initially} и \cdf{finally}, могут принимать любое количество
Lisp'овых форм и группировать в одиночную форму \cdf{progn}.
Loop clauses can contain auxiliary keywords, which are sometimes
called \emph{prepositions}. For example, the first clause in the
preceding code includes the prepositions \cdf{from} and \cdf{to},
which mark the value from which stepping begins and the value at which
stepping ends.
Выражения loop могут содержать вспомогательные ключевые символы,
которые иногда называются \emph{предлоги}. Например, первое выражение
в предыдущем коде включает предлоги \cdf{from} и \cdf{to}, которые
указывают на начальное и конечное значения для переменной.
\subsection{Order of Execution}
\subsection{Порядок вычисления}
With the exceptions listed below, clauses are executed in the loop
body in the order in which they appear in the source. Execution is
repeated until a clause terminates the loop or until a Common Lisp
\cdf{return}, \cdf{go}, or \cdf{throw} form is encountered. The
following actions are exceptions to the linear order of execution:
Выражения в теле loop вычисляются в том порядке, в котором задал
пользователь, с некоторыми исключениями перечисленными
ниже. Вычисление повторяется пока не сработает выражение, завершающее
цикл, или не будет вызвана одна из Common Lisp'овых форм \cdf{return},
\cdf{go}, \cdf{throw}. Для последовательного выполнения существуют
следующие исключения:
\begin{itemize}
\item All variables are initialized first, regardless of where the
establishing clauses appear in the source. The order of
initialization follows the order of these clauses.
\item Перво-наперво выполняется инициализация всех переменных, вне
зависимости от их позиции в исходном коде.
Порядок инициализации сохраняется.
\item The code for any \cdf{initially} clauses is collected into one
\cdf{progn} in the order in which the clauses appear in the source.
The collected code is executed once in the loop prologue after any
implicit variable initializations.
\item Код из всех \cdf{initially} выражений в исходном порядке
собирается в один большой \cdf{progn}. Собранный код вычисляется
единожды в прологе после инициализации всех переменных.
\item The code for any \cdf{finally} clauses is collected into one
\cdf{progn} in the order in which the clauses appear in the source.
The collected code is executed once in the loop epilogue before any
implicit values from the accumulation clauses are returned.
Explicit returns anywhere in the source, however, will exit the loop
without executing the epilogue code.
\item Код для всех \cdf{finally} выражение в исходном порядке
собирается в один большой \cdf{progn}. Собранный код вычисляется
единожды в эпилоге, перед тем как будут неявно возвращены значения
из цикла. Однако явный выход где-либо в исходнике, будет завершать
цикл без выполнения эпилога.
\item A \cdf{with} clause introduces a variable binding and an
optional initial value. The initial values are calculated in the
order in which the \cdf{with} clauses occur.
\item \cdf{with} выражение обозначает связывание переменной и
опционально первоначальное значение. Первоначальные значение
вычисляются в исходном порядке.
\item Iteration control clauses implicitly perform the following
actions:
\begin{itemize}
\item initializing variables
\item stepping variables, generally between each execution of the
loop body
\item performing termination tests, generally just before the
execution of the loop body
\end{itemize}
\item Выражения для итераций неявно выполняют следующие действия:
\begin{itemize}
\item присваивание переменных
\item наращивание переменных на каждой итерации
\item проверка условия завершения цикла, обычно перед выполнение итерации
\end{itemize}
\end{itemize}
\subsection{Kinds of Loop Clauses}
\label{LOOP-KINDS-SECTION}
\subsection{Разновидности Loop выражений}
Loop clauses fall into one of the following categories:
Выражения делятся на следующие категории:
\begin{itemize}
\item variable initialization and stepping
\item инициализация и пошаговое изменение
\begin{itemize}
\item The \cdf{for} and \cdf{as} constructs provide iteration
control clauses that establish a variable to be initialized. You
can combine \cdf{for} and \cdf{as} clauses with the loop keyword
\cdf{and} to get parallel initialization and stepping.
\item Конструкции \cdf{for} и \cdf{as} служат для установки
переменных. Для параллельной инициализации и изменения, выражения
\cdf{for} и \cdf{as} могут комбинироваться с помощью символа
\cdf{and}.
\item The \cdf{with} construct is similar to a single \cdf{let}
clause. You can combine \cdf{with} clauses using \cdf{and} to get
parallel initialization.
\item Конструкция \cdf{with} похожа на выражение \cdf{let}. Для
параллельной инициализации вы можете комбинировать \cdf{with} с
помощью \cdf{and}.
\item The \cdf{repeat} construct causes iteration to terminate after
a specified number of times. It uses an internal variable to keep
track of the number of iterations.
\item Конструкция \cdf{repeat} указывает на количество итераций. Она
использует внутреннюю переменную для подсчёта шагов.
\end{itemize}
You can specify data types for loop variables (see
section~\ref{LOOP-TYPES-SECTION}). It is an error to bind the same
variable twice in any variable-binding clause of a single loop
expression. Such variables include local variables, iteration
control variables, and variables found by destructuring.
Вы можете указать типы данных для переменных циклы (смотрите
раздел~\ref{LOOP-TYPES-SECTION}). Связывать переменные два раза в
одном цикле нельзя. Такие переменные включают локальные переменные,
переменные для управления циклом и переменные созданные при
деструктуризации.
\item value accumulation
\item накопление значения
\begin{itemize}
\item The \cdf{collect} construct takes one form in its clause and
adds the value of that form to the end of a list of values. By
default, the list of values is returned when the loop finishes.
\item Конструкция \cdf{collect} принимает одну форму и добавляет
значение этой формы в конец списка значений. По-умолчанию в конце
цикла этот список возвращается.
\item The \cdf{append} construct takes one form in its clause and
appends the value of that form to the end of a list of values. By
default, the list of values is returned when the loop finishes.
\item Конструкция \cdf{append} принимает одну форму и добавляет
значение этой формы в конец списка значений. По-умолчанию в конце
цикла этот список возвращается.
\item The \cdf{nconc} construct is similar to \cdf{append}, but its
list values are concatenated as if by the Common Lisp function
\cdf{nconc}. By default, the list of values is returned when the
loop finishes.
\item Конструкция \cdf{nconc} похожа на \cdf{append}, но список
соединяется с помощью функции \cdf{nconc}. По-умолчанию в конце
цикла этот список возвращается.
\item The \cdf{sum} construct takes one form in its clause that must
evaluate to a number and adds that number into a running total.
By default, the cumulative sum is returned when the loop finishes.
\item Конструкция \cdf{sum} принимает одну форму, которая должна
вернуть число, и добавляет это число в общую сумму. По-умолчанию
накопленная сумма возвращается из цикла.
\item The \cdf{count} construct takes one form in its clause and
counts the number of times that the form evaluates to a
non-\cdf{nil} value. By default, the count is returned when the
loop finishes.
\item Конструкция \cdf{count} принимает одну форму и подсчитывает
сколько раз эта форма вернула не-\cdf{nil} значение. По-умолчанию
это количество возвращается из цикла.
\item The \cdf{minimize} construct takes one form in its clause and
determines the minimum value obtained by evaluating that form. By
default, the minimum value is returned when the loop finishes.
\item Конструкция \cdf{minimize} принимает одну форму и сохраняет
минимальное значение, которое вернула эта форма. По-умолчанию,
минимальное значение возвращается из цикла.
\item The \cdf{maximize} construct takes one form in its clause and
determines the maximum value obtained by evaluating that form. By
default, the maximum value is returned when the loop finishes.
\item Конструкция \cdf{maximize} принимает одну форму и сохраняет
максимальное значение, которое вернула эта форма. По-умолчанию,
максимальное значение возвращается из цикла.
\end{itemize}
\item termination conditions
\item условия для завершения
\begin{itemize}
\item The \cdf{loop-finish} Lisp macro terminates iteration and
returns any accumulated result. If specified, any \cdf{finally}
clauses are evaluated.
\item Lisp'овые макрос \cdf{loop-finish} прекращает цикл и
возвращает накопленный результат. Вычисляется выражение
\cdf{finally}, если было указано.
\item The \cdf{for} and \cdf{as} constructs provide a termination
test that is determined by the iteration control clause.
\item Конструкции \cdf{for} и \cdf{as} завершают цикл после
выполнения указанных условий.
\item The \cdf{repeat} construct causes termination after a
specified number of iterations.
\item Конструкция \cdf{repeat} завершает цикл после выполнения
указанного количества итераций.
\item The \cdf{while} construct takes one form, a condition, and
terminates the iteration if the condition evaluates to \cdf{nil}.
A \cdf{while} clause is equivalent to the expression
\cd{(if~(not~\emph{condition}) (loop-finish))}.
\item Конструкция \cdf{while} принимает одну форму --- условие, и
завершает цикл когда условие возвращает \cdf{nil}. Выражение
\cdf{while} эквивалентно \cd{(if~(not~\emph{condition})
(loop-finish))}.
\item The \cdf{until} construct is the inverse of \cdf{while}; it
terminates the iteration if the condition evaluates to any
non-\cdf{nil} value. An \cdf{until} clause is equivalent to the
expression \cd{(if~\emph{condition} (loop-finish))}.
\item Конструкция \cdf{until} антоним конструкции \cdf{while}. Она
завершает цикл, когда условие возвращает не-\cdf{nil}
значение. Выражение \cdf{until} эквивалентно
\cd{(if~\emph{condition} (loop-finish))}.
\item The \cdf{always} construct takes one form and terminates the
loop if the form ever evaluates to \cdf{nil}; in this case, it
returns \cdf{nil}. Otherwise, it provides a default return value
of \cdf{t}.
\item Конструкция \cdf{always} принимает одну форму и завершает
цикл, если форма возвращает \cdf{nil}, в этом случае возвращается
\cdf{nil}. Иначе возвращается результат по-умолчанию \cdf{t}.
\item The \cdf{never} construct takes one form and terminates the
loop if the form ever evaluates to non-\cdf{nil}; in this case, it
returns \cdf{nil}. Otherwise, it provides a default return value
of \cdf{t}.
\item Конструкция \cdf{never} принимает одну форму и завершает
цикл, если форма возвращает \cdf{nil}, в этом случае возвращается
\cdf{nil}. Иначе возвращается результат по-умолчанию \cdf{t}.
\item The \cdf{thereis} construct takes one form and terminates the
loop if the form ever evaluates to non-\cdf{nil}; in this case, it
returns that value.
\item Конструкция \cdf{thereis} принимает одну форму и завершает
цикле, если форма возвращает не-\cdf{nil}, в этом случае
возвращается значение формы.
\end{itemize}
\item unconditional execution
\item безусловное выполнение
\begin{itemize}
\item The \cdf{do} construct simply evaluates all forms in its
clause.
\item Конструкция \cdf{do} просто выполняет все переданные формы.
\item The \cdf{return} construct takes one form and returns its
value. It is equivalent to the clause \cd{do (return \emph{value})}.
\item Конструкция \cdf{return} принимает одну форму и возвращает её
значение. Эквивалентное выражение \cd{do (return \emph{value})}.
\end{itemize}
\item conditional execution
\item условное выполнение
\begin{itemize}
\item The \cdf{if} construct takes one form as a predicate and a
clause that is executed when the predicate is true. The clause can
be a value accumulation, unconditional, or another conditional
clause; it can also be any combination of such clauses connected
by the loop keyword \cdf{and}.
\item Конструкция \cdf{if} принимает форму в качестве предиката и
выражение, которое выполняется в случае истинности
предиката. Выражение может быть накоплением значения, безусловным
или другим условным выражением.
\item The \cdf{when} construct is a synonym for \cdf{if}.
\item Конструкция \cdf{when} это синоним для конструкции \cdf{if}.
\item The \cdf{unless} construct is similar to \cdf{when} except
that it complements the predicate; it executes the following
clause if the predicate is false.
\item Конструкция \cdf{unless} похожа на \cdf{when} кроме того, что
она выполняет форму при условии что предикат ложен.
\item The \cdf{else} construct provides an optional component of
\cdf{if}, \cdf{when}, and \cdf{unless} clauses that is executed
when the predicate is false. The component is one of the clauses
described under \cdf{if}.
\item Конструкция \cdf{else} содержит компонент, который будет
выполнен при невыполнении веток \cdf{if}, \cdf{when} и
\cdf{unless}.
\item The \cdf{end} construct provides an optional component to mark
the end of a conditional clause.
\item Конструкция \cdf{end} указывает на конец условного выражения.
\end{itemize}
\item miscellaneous operations
\item дополнительные операции
\begin{itemize}
\item The \cdf{named} construct assigns a name to a loop construct.
\item Конструкция \cdf{named} присваивает имя блоку цикла.
\item The \cdf{initially} construct causes its forms to be evaluated
in the loop prologue, which precedes all loop code except for
initial settings specified by the constructs \cdf{with},
\cdf{for}, or \cdf{as}.
\item Конструкция \cdf{initially} вычисляет формы в прологе цикла,
который следует перед телом цикла, но после первоначальных
связываний в конструкциях \cdf{with}, \cdf{for} и \cdf{as}.
\item The \cdf{finally} construct causes its forms to be evaluated
in the loop epilogue after normal iteration terminates. An
unconditional clause can also follow the loop keyword
\cdf{finally}.
\item Конструкция \cdf{finally} выполняет формы в эпилоге цикла
после завершения итераций. Кроме того после слова \cdf{finally}
могут следовать безусловные выражения.
\end{itemize}
\end{itemize}
\subsection{Loop Syntax}
\subsection{Синтаксис Loop}
The following syntax description provides an overview of the syntax
for loop clauses. Detailed syntax descriptions of individual clauses
appear in sections~\ref{LOOP-ITERATION-SECTION}
through~\ref{LOOP-MISC-SECTION}. A loop consists of the following
types of clauses:
\begin{tabbing} \emph{initial-final\/} ::= \emph{initially\/} {\Mor}
\emph{finally\/} \\* \emph{variables\/} ::= \emph{with\/} {\Mor}
\emph{initial-final\/} {\Mor} \emph{for-as\/} {\Mor} \emph{repeat} \\*
\emph{main\/} ::= \emph{unconditional\/} {\Mor} \emph{accumulation\/}
{\Mor} \emph{conditional\/} {\Mor} \emph{termination\/} {\Mor}
\emph{initial-final\/} \\* \emph{loop\/} ::= \cd{(loop \Mopt{\cd{named
\emph{name\/}}} \Mstar\emph{variables\/} \Mstar\emph{main\/})}
\end{tabbing}
Вот небольшой обзор синтаксиса для выражений цикла. Детальные описания
конкретных подвыражений находятся в разделах начиная
с~\ref{LOOP-ITERATION-SECTION} и
заканчивая~\ref{LOOP-MISC-SECTION}. Цикл содержит следующие типы
выражений:
\begin{tabbing} \emph{initial-final\/} ::= \emph{initially\/} {\Mor}
\emph{finally\/} \\* \emph{variables\/} ::= \emph{with\/} {\Mor}
\emph{initial-final\/} {\Mor} \emph{for-as\/} {\Mor} \emph{repeat} \\*
\emph{main\/} ::= \emph{unconditional\/} {\Mor} \emph{accumulation\/}
{\Mor} \emph{conditional\/} {\Mor} \emph{termination\/} {\Mor}
\emph{initial-final\/} \\* \emph{loop\/} ::= \cd{(loop \Mopt{\cd{named
\emph{name\/}}} \Mstar\emph{variables\/} \Mstar\emph{main\/})}
\end{tabbing}
Note that a loop must have at least one clause; however, for backward
compatibility, the following format is also supported:
\begin{lisp} (loop \Mstar{\emph{tag} {\Mor} \emph{expr}})
\end{lisp} where \emph{expr} is any Common Lisp expression that can be
evaluated, and \emph{tag} is any symbol not identifiable as a loop
keyword. Such a format is roughly equivalent to the following one:
\begin{lisp} (loop do \Mstar{\emph{tag} {\Mor} \emph{expr}})
\end{lisp}
Заметьте, что цикл должен содержать как минимум одно выражение, однако
для обратной совместимости также поддерживается и следующий формат:
\begin{lisp} (loop \Mstar{\emph{tag} {\Mor} \emph{expr}})
\end{lisp}
где \emph{expr} является любым Common Lisp'овым выражением, которое
может быть вычислено, и \emph{tag} это любой символ не из множества
символов loop. Такой формат примерно эквивалентен следующему:
\begin{lisp} (loop do \Mstar{\emph{tag} {\Mor} \emph{expr}})
\end{lisp}
A loop prologue consists of any automatic variable initializations
prescribed by the \emph{variable\/} clauses, along with any
\emph{initially\/} clauses in the order they appear in the source.
Пролог состоит из инициализации переменных описанных в соответствующих
выражения, и \cdf{initially} выражений в том порядке, в котором они
были записаны.
A loop epilogue consists of \emph{finally\/} clauses, if any, along
with any implicit return value from an \emph{accumulation\/} clause or
an \emph{end-test\/} clause.
Эпилог состоит из выражений \cdf{finally} (если они были), и неявного
возврата значения из выражений собирающих результат или из выражений
проверки выхода из цикла.
\section{User Extensibility}
There is currently no specified portable method for users to add
extensions to the Loop Facility. The names \cdf{defloop} and
\cdf{define-loop-method} have been suggested as candidates for such a
method.
\section{Пользовательские расширения}
Пользователю не предоставляется способа расширить функционал Loop.
\section{Loop Constructs}
\section{Конструкции Loop}
The remaining sections of this chapter describe the constructs that
the Loop Facility provides. The descriptions are organized according
to the functionality of the constructs. Each section begins with a
general discussion of a particular operation; it then presents the
constructs that perform the operation.
Следующие разделы раскрывают конструкции цикла Loop. Описания
сгруппированы по типам данных конструкций. Каждый раздел начинается с
общего описания конкретной операции, затем раскрывается конструкция,
которая выполняет данную операцию.
\begin{itemize}
\item Section~\ref{LOOP-ITERATION-SECTION}, ``Iteration Control,''
describes iteration control clauses that allow directed loop
iteration.
\item Раздел~\ref{LOOP-ITERATION-SECTION}, <<Управление итерациями>>
описывает выражения для управления итерациями.
\item Section~\ref{LOOP-TEST-SECTION}, ``End-Test Control,'' describes
clauses that stop iteration by providing a conditional expression
that can be tested after each execution of the loop body.
\item Раздел~\ref{LOOP-TEST-SECTION}, <<Проверка завершения>>
описывает выражения, которые прекращают итерации, в случае если того
требует тестовое выражение, которые выполняется на каждой итерации.
\item Section~\ref{LOOP-ACCUM-SECTION}, ``Value Accumulation,''
describes constructs that accumulate values during iteration and
return them from a loop. This section also discusses ways in which
accumulation clauses can be combined within the Loop Facility.
\item Раздел~\ref{LOOP-ACCUM-SECTION}, <<Накопление значения>>
описывает конструкции, которые накапливают значение во время
итераций и возвращают их из цикла. Данный раздел также содержит
методы комбинирования данных выражений с другим функционалом.
\item Section~\ref{LOOP-VAR-SECTION}, ``Variable Initializations,''
describes the \cdf{with} construct, which provides local variables
for use within the loop body, and other constructs that provide
local variables.
\item Раздел~\ref{LOOP-VAR-SECTION}, <<Инициализация переменных>>
описывает конструкцию \cdf{with}, которая позволяет создавать
локальные переменные для использования в теле цикла, а также другие
конструкции, которые создают локальные переменные.
\item Section~\ref{LOOP-COND-SECTION}, ``Conditional Execution,''
describes how to execute loop clauses conditionally.
\item Раздел~\ref{LOOP-COND-SECTION}, <<Условное выполнение>>
описывает то, как выполнять выражения цикла в зависимости от
условия.
\item Section~\ref{LOOP-UNCOND-SECTION}, ``Unconditional Execution,''
describes the \cdf{do} and \cdf{return} constructs. It also
describes constructs that are used in the loop prologue and loop
epilogue.
\item Раздел~\ref{LOOP-UNCOND-SECTION}, <<Безусловное выполнение>>
описывает конструкции \cdf{do} и \cdf{return}. Раздел также содержит
информацию о прологе и эпилоге цикла Loop.
\item Section~\ref{LOOP-MISC-SECTION}, ``Miscellaneous Features,''
discusses loop data types and destructuring. It also presents
constructs for naming a loop and for specifying initial and final
actions.
\item Раздел~\ref{LOOP-MISC-SECTION} <<Дополнительные возможности>>
описывает типы данных и деструктуризацию в контексте цикла
loop. Раздел также содержит информацию о задании имени цикла и
прологе и эпилоге.
\end{itemize}
\section{Iteration Control}
\label{LOOP-ITERATION-SECTION}
\section{Управление итерациями}
\label{LOOP-ITERATION-SECTION}
Iteration control clauses allow you to direct loop iteration. The
loop keywords \cdf{as}, \cdf{for}, and \cdf{repeat} designate iteration control clauses.
Для управления итерациями используются выражения \cdf{as}, \cdf{for} и \cdf{repeat}.
Iteration control clauses differ with respect to the specification of
termination conditions and the initialization and stepping
of loop variables. Iteration clauses by themselves
do not cause the Loop Facility to return values, but they
can be used in conjunction with value-accumulation clauses to
return values (see section~\ref{LOOP-ACCUM-SECTION}).
Управление итерациями отличается от условий завершения цикла и
инициализации и наращивания переменных цикла. Управление итерациями
само по себе не выполняет возврат значение, но оно может
использоваться в сочетании с выражениями накопления значения для
возврата значений (смотрите раздел~\ref{LOOP-ACCUM-SECTION}).
All variables are initialized in the loop prologue. The scope of
the variable binding is \emph{lexical} unless it is proclaimed
special; thus, the variable can be
accessed only by expressions that lie textually within the loop.
Stepping assignments are made in the loop body before any other expressions
are evaluated in the body.
Все переменные инициализируются в прологе цикла. Область видимости
переменных \emph{лексическая}, если только они не объявлены как
\emph{специальные}. Таким образом переменные доступны только в
выражениях, которые текстово находятся в цикле. Наращивание переменных
выполняется в теле цикла перед другими выражениями.
The variable argument in iteration control clauses can be a
\emph{destructuring list}. A destructuring list
is a tree whose non-null atoms are symbols that
can be assigned a value (see section~\ref{LOOP-DESTRUCTURING-SECTION}).
На месте переменное может стоять \emph{список переменных для
деструктуризации}. Данный список представляет из себя дерево, в
котором не-null атомы это символы, которые могут быть связаны со
значениями (смотрите раздел~\ref{LOOP-DESTRUCTURING-SECTION}).
The iteration control clauses \cdf{for}, \cdf{as}, and \cdf{repeat}
must precede any other loop clauses except
\cdf{initially}, \cdf{with}, and \cdf{named},
since they establish variable bindings. When iteration control clauses are
used in a loop, termination tests in the loop body are evaluated
before any other loop body code is executed.
Выражения для управления итерациями \cdf{for}, \cdf{as} и \cdf{repeat}
должны быть указаны прежде других выражений за исключением
\cdf{initially}, \cdf{with} и \cdf{named}, так как последние служат
для создания переменных. При использовании выражений управления
итерациями, проверка завершения выполняется перед самим телом цикла.
If you use multiple iteration clauses to control iteration, variable
initialization and stepping occur sequentially by default.
You can use the \cdf{and} construct to connect two or more
iteration clauses when sequential binding and stepping are not necessary.
The iteration behavior of clauses joined by \cdf{and}
is analogous to the behavior of the Common Lisp macro \cdf{do}
relative to \cdf{do*}.
Если вы используете несколько выражений для управления итерациями,
по-умолчанию связывания и наращивания переменных выполняются
последовательно. Если последовательное выполнение необязательно, вы
можете объединить выражения с помощью конструкции \cdf{and}. Различия
при неиспользовании и использовании конструкции \cdf{and} аналогичны
различиям между \cdf{do} и \cdf{do*}
In the following example, the variable \cdf{x} is stepped
before \cdf{y} is stepped; thus, the value of \cdf{y}
reflects the updated value of \cdf{x}:
\begin{lisp}
(loop for x from 1 to 9 \\*
~~~~~~for y = nil then x \\*
~~~~~~collect (list x y)) \\*
~~~\EV~((1 NIL) (2 2) (3 3) (4 4) (5 5) (6 6) (7 7) (8 8) (9 9))
\end{lisp}
In the following example, \cdf{x} and \cdf{y} are stepped in parallel:
\begin{lisp}
(loop for x from 1 to 9 \\*
~~~~~~and y = nil then x \\*
~~~~~~collect (list x y)) \\*
~~~\EV~((1 NIL) (2 1) (3 2) (4 3) (5 4) (6 5) (7 6) (8 7) (9 8))
\end{lisp}
В следующем примере переменная \cdf{x} наращивается прежде чем
\cdf{y}, таким образом \cdf{y} содержит новое значение \cdf{x}.
\begin{lisp}
(loop for x from 1 to 9 \\*
~~~~~~for y = nil then x \\*
~~~~~~collect (list x y)) \\*
~~~\EV~((1 NIL) (2 2) (3 3) (4 4) (5 5) (6 6) (7 7) (8 8) (9 9))
\end{lisp}
В следующем примере переменные \cdf{x} и \cdf{y} наращиваются
параллельно:
\begin{lisp}
(loop for x from 1 to 9 \\*
~~~~~~and y = nil then x \\*
~~~~~~collect (list x y)) \\*
~~~\EV~((1 NIL) (2 1) (3 2) (4 3) (5 4) (6 5) (7 6) (8 7) (9 8))
\end{lisp}
The \cdf{for} and \cdf{as} clauses iterate by using one or more local
loop variables that are initialized to some value and that
can be modified or stepped after each iteration.
For these clauses, iteration terminates when a local
variable reaches some specified value or when some other loop clause
terminates iteration. At each iteration, variables can be stepped by an
increment or a decrement or can be assigned a new value by
the evaluation of
an expression. Destructuring can be used to assign initial values to
variables during iteration.
Выражения \cdf{for} и \cdf{as} выполняют тело цикла для одной или
нескольких переменных, которые вначале инициализируются некоторым
значением, затем наращиваются после каждой итерации. Для этих
выражений цикл завершается после того, как локальная переменная
достигает последнего указанного значения, или срабатывает какое-либо
другое завершающее выражение. На каждой итерации переменная может быть
увеличена, уменьшена, или ей может быть связана с значением некоторого
выражения. Для присваивания первоначальных значений может
использоваться деструктуризация.
The \cdf{for} and \cdf{as} keywords are synonyms and may be used
interchangeably. There are
seven syntactic representations for these constructs.
In each syntactic description, the data type of
\emph{var\/} can be specified by the optional \emph{type-spec\/}
argument. If \emph{var\/} is a destructuring list, the data type
specified by the \emph{type-spec\/} argument must appropriately match
the elements of the list (see sections~\ref{LOOP-TYPES-SECTION}
and~\ref{LOOP-DESTRUCTURING-SECTION}).
Ключевые символы \cdf{for} и \cdf{as} являются синонимами,
соответственно взаимозаменяемы. Для этих конструкций существует семь
синтаксических представлений. В каждой из них для переменной
\emph{var} опционально можно задать тип \emph{type-spec}. Если
\emph{var} является списком для деструктуризации, \emph{type-spec}
должен соответственно описывать элементы списка (смотрите
разделы~\ref{LOOP-TYPES-SECTION} и~\ref{LOOP-DESTRUCTURING-SECTION})
\begin{defloop}
for var [type-spec] [{\!from! | \!downfrom! | \!upfrom!} expr1]
[{\!to! | \!downto! | \!upto! | \!below! | \!above!} expr2]
[\!by! expr3] \\
as var [type-spec] [{\!from! | \!downfrom! | \!upfrom!} expr1]
[{\!to! | \!downto! | \!upto! | \!below! | \!above!} expr2]
[\!by! expr3]
[This is the first of seven \cdf{for}/\cdf{as} syntaxes.---GLS]
The \cdf{for} or \cdf{as} construct iterates from the value specified by
\emph{expr1\/} to the value specified by \emph{expr2\/} in increments or
decrements denoted by \emph{expr3}. Each
expression is evaluated only once and must evaluate to a number.
The variable \emph{var\/} is bound to the value of
\emph{expr1\/} in the first iteration and is stepped
by the value of \emph{expr3\/} in each succeeding iteration,
or by 1 if \emph{expr3\/} is not provided.
The following loop keywords serve as valid prepositions within this
syntax.
\begin{flushdesc}
\item[\cdf{from}]
The loop keyword \cdf{from} marks the value from which
stepping begins, as specified by \emph{expr1}.
Stepping is incremental by default. For
decremental stepping, use \cdf{above}
or \cdf{downto} with \emph{expr2}. For incremental
stepping, the default \cdf{from} value is \cd{0}.
\item[\cdf{downfrom}, \cdf{upfrom}]
The loop keyword \cdf{downfrom}
indicates that the variable \emph{var\/} is decreased in decrements
specified by \emph{expr3}; the loop keyword \cdf{upfrom} indicates that
\emph{var\/} is increased in increments specified by \emph{expr3}.
\item[\cdf{to}]
The loop keyword \cdf{to} marks the end value for stepping specified in
\emph{expr2}. Stepping is incremental by default. For
decremental stepping, use \cdf{downto},
\cdf{downfrom}, or \cdf{above} with \emph{expr2}.
\item[\cdf{downto}, \cdf{upto}]
The loop keyword \cdf{downto} allows iteration to proceed
from a larger number to a smaller number by the decrement
\emph{expr3}. The loop keyword \cdf{upto} allows iteration to proceed
from a smaller number to a larger number by the increment \emph{expr3}.
Since there is no default for \emph{expr1\/} in decremental stepping,
you must supply a value with \cdf{downto}.
\item[\cdf{below}, \cdf{above}]
The loop keywords \cdf{below} and \cdf{above} are analogous to
\cdf{upto} and \cdf{downto}, respectively. These keywords stop
iteration just before the value of the variable \emph{var} reaches the value
specified by \emph{expr2\/}; the end value of \emph{expr2\/} is not included.
Since there is no default for \emph{expr1\/} in decremental stepping,
you must supply a value with \cdf{above}.
\item[\cdf{by}]
The loop keyword \cdf{by} marks the increment or decrement specified by
\emph{expr3}. The value of \emph{expr3\/} can be any positive number.
The default value is \cd{1}.
\end{flushdesc}
At least one of these prepositions must be used with this syntax.
In an iteration control clause, the \cdf{for} or \cdf{as} construct
causes termination when the specified limit is reached. That is,
iteration continues until the value \emph{var\/} is stepped to the
exclusive or inclusive limit specified by \emph{expr2\/}. The range is
\emph{exclusive\/} if \emph{expr3\/} increases or decreases \emph{var\/}
to the value of \emph{expr2\/} without reaching that value; the loop
keywords \cdf{below} and \cdf{above} provide exclusive limits. An
\emph{inclusive\/} limit allows \emph{var\/} to attain the value of
\emph{expr2}; \cdf{to}, \cdf{downto}, and \cdf{upto} provide inclusive
limits.
A common convention is to use \cdf{for} to introduce new iterations and \cdf{as}
to introduce iterations that depend on a previous iteration specification.
[However, \cdf{loop} does not enforce this convention, and some of the examples
below violate it. \emph{De gustibus non disputandum est.}---GLS]
Examples:
\begin{lisp}
;;; Print some numbers. \\[3pt]
(loop as i from 1 to 5 \\*
~~~~~~do (print i)) \`;\textrm{Prints 5 lines} \\
1 \\*
2 \\*
3 \\*
4 \\*
5 \\*
~~~\EV~NIL \\
\\
;;; Print every third number. \\[3pt]
(loop for i from 10 downto 1 by 3 \\*
~~~~~~do (print i)) \`;\textrm{Prints 4 lines}\\
10 \\*
7 \\*
4 \\*
1 \\*
~~~\EV~NIL
\end{lisp}
\begin{lisp}
;;; Step incrementally from the default starting value. \\[3pt]
(loop as i below 5 \\*
~~~~~~do (print i)) \`;\textrm{Prints 5 lines} \\
0 \\*
1 \\*
2 \\*
3 \\*